blob: 8eb6a5fa5a026e6a078dd3db9533fd63f43df974 [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
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000010#include <vector>
11
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000012#include "CommandObjectBreakpoint.h"
13#include "CommandObjectBreakpointCommand.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014#include "lldb/Breakpoint/Breakpoint.h"
15#include "lldb/Breakpoint/BreakpointIDList.h"
16#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000017#include "lldb/Host/OptionParser.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000018#include "lldb/Interpreter/CommandCompletions.h"
19#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
Pavel Labath47cbf4a2018-04-10 09:03:59 +000021#include "lldb/Interpreter/OptionArgParser.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000022#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000023#include "lldb/Interpreter/OptionValueString.h"
24#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000025#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000026#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000027#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000028#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000029#include "lldb/Target/Thread.h"
30#include "lldb/Target/ThreadSpec.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000031#include "lldb/Utility/RegularExpression.h"
32#include "lldb/Utility/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033
34using namespace lldb;
35using namespace lldb_private;
36
Kate Stoneb9c1b512016-09-06 20:57:50 +000037static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38 lldb::DescriptionLevel level) {
39 s->IndentMore();
40 bp->GetDescription(s, level, true);
41 s->IndentLess();
42 s->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043}
44
Jim Inghamb842f2e2017-09-14 20:22:49 +000045//-------------------------------------------------------------------------
46// Modifiable Breakpoint Options
47//-------------------------------------------------------------------------
48#pragma mark Modify::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000049static constexpr OptionDefinition g_breakpoint_modify_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +000050 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000051 { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
52 { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
53 { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
54 { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
55 { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
56 { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
57 { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
58 { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
59 { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." },
60 { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." },
61 { 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 +000062 // clang-format on
63};
64class lldb_private::BreakpointOptionGroup : public OptionGroup
65{
66public:
67 BreakpointOptionGroup() :
68 OptionGroup(),
69 m_bp_opts(false) {}
70
71 ~BreakpointOptionGroup() override = default;
72
73 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
74 return llvm::makeArrayRef(g_breakpoint_modify_options);
75 }
76
77 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
78 ExecutionContext *execution_context) override {
79 Status error;
80 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
81
82 switch (short_option) {
83 case 'c':
Adrian Prantl05097242018-04-30 16:49:04 +000084 // Normally an empty breakpoint condition marks is as unset. But we need
85 // to say it was passed in.
Jim Inghamb842f2e2017-09-14 20:22:49 +000086 m_bp_opts.SetCondition(option_arg.str().c_str());
87 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
88 break;
89 case 'C':
90 m_commands.push_back(option_arg);
91 break;
92 case 'd':
93 m_bp_opts.SetEnabled(false);
94 break;
95 case 'e':
96 m_bp_opts.SetEnabled(true);
97 break;
98 case 'G': {
99 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000100 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000101 if (success) {
102 m_bp_opts.SetAutoContinue(value);
103 } else
104 error.SetErrorStringWithFormat(
105 "invalid boolean value '%s' passed for -G option",
106 option_arg.str().c_str());
107 }
108 break;
109 case 'i':
110 {
111 uint32_t ignore_count;
112 if (option_arg.getAsInteger(0, ignore_count))
113 error.SetErrorStringWithFormat("invalid ignore count '%s'",
114 option_arg.str().c_str());
115 else
116 m_bp_opts.SetIgnoreCount(ignore_count);
117 }
118 break;
119 case 'o': {
120 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000121 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000122 if (success) {
123 m_bp_opts.SetOneShot(value);
124 } else
125 error.SetErrorStringWithFormat(
126 "invalid boolean value '%s' passed for -o option",
127 option_arg.str().c_str());
128 } break;
129 case 't':
130 {
131 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
132 if (option_arg[0] != '\0') {
133 if (option_arg.getAsInteger(0, thread_id))
134 error.SetErrorStringWithFormat("invalid thread id string '%s'",
135 option_arg.str().c_str());
136 }
137 m_bp_opts.SetThreadID(thread_id);
138 }
139 break;
140 case 'T':
141 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
142 break;
143 case 'q':
144 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
145 break;
146 case 'x':
147 {
148 uint32_t thread_index = UINT32_MAX;
149 if (option_arg[0] != '\n') {
150 if (option_arg.getAsInteger(0, thread_index))
151 error.SetErrorStringWithFormat("invalid thread index string '%s'",
152 option_arg.str().c_str());
153 }
154 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
155 }
156 break;
157 default:
158 error.SetErrorStringWithFormat("unrecognized option '%c'",
159 short_option);
160 break;
161 }
162
163 return error;
164 }
165
166 void OptionParsingStarting(ExecutionContext *execution_context) override {
167 m_bp_opts.Clear();
168 m_commands.clear();
169 }
170
171 Status OptionParsingFinished(ExecutionContext *execution_context) override {
172 if (!m_commands.empty())
173 {
174 if (!m_commands.empty())
175 {
176 auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
177
178 for (std::string &str : m_commands)
179 cmd_data->user_source.AppendString(str);
180
181 cmd_data->stop_on_error = true;
182 m_bp_opts.SetCommandDataCallback(cmd_data);
183 }
184 }
185 return Status();
186 }
187
188 const BreakpointOptions &GetBreakpointOptions()
189 {
190 return m_bp_opts;
191 }
192
193 std::vector<std::string> m_commands;
194 BreakpointOptions m_bp_opts;
195
196};
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000197static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000198 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000199 { 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 +0000200 "which prime new targets." },
201 // clang-format on
202};
203
204class BreakpointDummyOptionGroup : public OptionGroup
205{
206public:
207 BreakpointDummyOptionGroup() :
208 OptionGroup() {}
209
210 ~BreakpointDummyOptionGroup() override = default;
211
212 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
213 return llvm::makeArrayRef(g_breakpoint_dummy_options);
214 }
215
216 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
217 ExecutionContext *execution_context) override {
218 Status error;
219 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
220
221 switch (short_option) {
222 case 'D':
223 m_use_dummy = true;
224 break;
225 default:
226 error.SetErrorStringWithFormat("unrecognized option '%c'",
227 short_option);
228 break;
229 }
230
231 return error;
232 }
233
234 void OptionParsingStarting(ExecutionContext *execution_context) override {
235 m_use_dummy = false;
236 }
237
238 bool m_use_dummy;
239
240};
241
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000242// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
243// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
Jim Ingham3815e702018-09-13 21:35:32 +0000244#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10)
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000245#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
Jim Ingham3815e702018-09-13 21:35:32 +0000246#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10)
247#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2)
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000248#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
249#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
250
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000251static constexpr OptionDefinition g_breakpoint_set_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000252 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000253 { 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 +0000254 "multiple times to specify multiple shared libraries." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000255 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
256 { 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 +0000257 "lldb only looks for files that are #included if they use the standard include "
258 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
259 "#included, set target.inline-breakpoint-strategy to \"always\"." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000260 { 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 +0000261
Adrian Prantl05097242018-04-30 16:49:04 +0000262 // Comment out this option for the moment, as we don't actually use it, but
263 // will in the future. This way users won't see it, but the infrastructure is
264 // left in place.
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000265 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
266 // "Set the breakpoint by source location at this particular column."},
267
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000268 { 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 +0000269 "a particular binary, then the address will be converted to a \"file\" "
270 "address, so that the breakpoint will track that binary+offset no matter where "
271 "the binary eventually loads. Alternately, if you also specify the module - "
272 "with the -s option - then the address will be treated as a file address in "
273 "that module, and resolved accordingly. Again, this will allow lldb to track "
274 "that offset on subsequent reloads. The module need not have been loaded at "
275 "the time you specify this breakpoint, and will get resolved when the module "
276 "is loaded." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000277 { 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 +0000278 "one breakpoint for multiple names" },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000279 { 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 +0000280 "functions. Can be repeated multiple times." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000281 { 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 +0000282 "namespaces and all arguments, and for Objective-C this means a full function "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000283 "prototype with class and selector. Can be repeated multiple times to make "
284 "one breakpoint for multiple names." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000285 { 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 +0000286 "make one breakpoint for multiple Selectors." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000287 { 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 +0000288 "make one breakpoint for multiple methods." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000289 { 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 +0000290 "the function name(s)." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000291 { 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 +0000292 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
293 "symbols." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000294 { 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 +0000295 "against the source text in a source file or files specified with the -f "
296 "option. The -f option can be specified more than once. If no source files "
297 "are specified, uses the current \"default source file\". If you want to "
298 "match against all source files, pass the \"--all-files\" option." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000299 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." },
300 { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." },
301 { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
302 { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." },
303 { 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 +0000304 "options, on throw but not catch.)" },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000305 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
306 { 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 +0000307
308 // Don't add this option till it actually does something useful...
309 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
310 // "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" },
311
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000312 { 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 +0000313 "(note: currently only implemented for setting breakpoints on identifiers). "
314 "If not set the target.language setting is used." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000315 { 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 +0000316 "If not set the target.skip-prologue setting is used." },
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000317 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
318 { 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 +0000319 "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 +0000320 { 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 +0000321 "setting is used." },
322 // clang-format on
323};
324
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000326// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000327//-------------------------------------------------------------------------
328
Kate Stoneb9c1b512016-09-06 20:57:50 +0000329class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000330public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000331 typedef enum BreakpointSetType {
332 eSetTypeInvalid,
333 eSetTypeFileAndLine,
334 eSetTypeAddress,
335 eSetTypeFunctionName,
336 eSetTypeFunctionRegexp,
337 eSetTypeSourceRegexp,
Jim Ingham3815e702018-09-13 21:35:32 +0000338 eSetTypeException,
339 eSetTypeScripted,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340 } BreakpointSetType;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000341
Kate Stoneb9c1b512016-09-06 20:57:50 +0000342 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
343 : CommandObjectParsed(
344 interpreter, "breakpoint set",
345 "Sets a breakpoint or set of breakpoints in the executable.",
346 "breakpoint set <cmd-options>"),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000347 m_bp_opts(), m_options() {
348 // We're picking up all the normal options, commands and disable.
349 m_all_options.Append(&m_bp_opts,
350 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
351 LLDB_OPT_SET_ALL);
352 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
353 m_all_options.Append(&m_options);
354 m_all_options.Finalize();
355 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356
357 ~CommandObjectBreakpointSet() override = default;
358
Jim Inghamb842f2e2017-09-14 20:22:49 +0000359 Options *GetOptions() override { return &m_all_options; }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000360
Jim Inghamb842f2e2017-09-14 20:22:49 +0000361 class CommandOptions : public OptionGroup {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362 public:
363 CommandOptions()
Jim Inghamb842f2e2017-09-14 20:22:49 +0000364 : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
366 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
368 m_exception_language(eLanguageTypeUnknown),
369 m_language(lldb::eLanguageTypeUnknown),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000370 m_skip_prologue(eLazyBoolCalculate),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000371 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
372
373 ~CommandOptions() override = default;
374
Zachary Turner97206d52017-05-12 04:51:55 +0000375 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
376 ExecutionContext *execution_context) override {
377 Status error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000378 const int short_option = g_breakpoint_set_options[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000379
380 switch (short_option) {
381 case 'a': {
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000382 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
383 LLDB_INVALID_ADDRESS, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384 } break;
385
386 case 'A':
387 m_all_files = true;
388 break;
389
390 case 'b':
391 m_func_names.push_back(option_arg);
392 m_func_name_type_mask |= eFunctionNameTypeBase;
393 break;
394
Zachary Turnerfe114832016-11-12 16:56:47 +0000395 case 'C':
396 if (option_arg.getAsInteger(0, m_column))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 error.SetErrorStringWithFormat("invalid column number: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000398 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000399 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000400
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401 case 'E': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000402 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000403
404 switch (language) {
405 case eLanguageTypeC89:
406 case eLanguageTypeC:
407 case eLanguageTypeC99:
408 case eLanguageTypeC11:
409 m_exception_language = eLanguageTypeC;
410 break;
411 case eLanguageTypeC_plus_plus:
412 case eLanguageTypeC_plus_plus_03:
413 case eLanguageTypeC_plus_plus_11:
414 case eLanguageTypeC_plus_plus_14:
415 m_exception_language = eLanguageTypeC_plus_plus;
416 break;
417 case eLanguageTypeObjC:
418 m_exception_language = eLanguageTypeObjC;
419 break;
420 case eLanguageTypeObjC_plus_plus:
421 error.SetErrorStringWithFormat(
422 "Set exception breakpoints separately for c++ and objective-c");
423 break;
424 case eLanguageTypeUnknown:
425 error.SetErrorStringWithFormat(
426 "Unknown language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000427 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000428 break;
429 default:
430 error.SetErrorStringWithFormat(
431 "Unsupported language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000432 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000433 }
434 } break;
435
436 case 'f':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000437 m_filenames.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000438 break;
439
440 case 'F':
441 m_func_names.push_back(option_arg);
442 m_func_name_type_mask |= eFunctionNameTypeFull;
443 break;
Jim Inghamf08f5c92017-08-03 18:13:24 +0000444
Kate Stoneb9c1b512016-09-06 20:57:50 +0000445 case 'h': {
446 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000447 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 if (!success)
449 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000450 "Invalid boolean value for on-catch option: '%s'",
451 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000452 } break;
453
454 case 'H':
455 m_hardware = true;
456 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000457
458 case 'k': {
459 if (m_current_key.empty())
460 m_current_key.assign(option_arg);
461 else
462 error.SetErrorStringWithFormat("Key: %s missing value.",
463 m_current_key.c_str());
464
465 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466 case 'K': {
467 bool success;
468 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000469 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470 if (value)
471 m_skip_prologue = eLazyBoolYes;
472 else
473 m_skip_prologue = eLazyBoolNo;
474
475 if (!success)
476 error.SetErrorStringWithFormat(
477 "Invalid boolean value for skip prologue option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000478 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000479 } break;
480
Zachary Turnerfe114832016-11-12 16:56:47 +0000481 case 'l':
482 if (option_arg.getAsInteger(0, m_line_num))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000483 error.SetErrorStringWithFormat("invalid line number: %s.",
Zachary Turnerfe114832016-11-12 16:56:47 +0000484 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000486
487 case 'L':
Zachary Turnerfe114832016-11-12 16:56:47 +0000488 m_language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000489 if (m_language == eLanguageTypeUnknown)
490 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000491 "Unknown language type: '%s' for breakpoint",
492 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000493 break;
494
495 case 'm': {
496 bool success;
497 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000498 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000499 if (value)
500 m_move_to_nearest_code = eLazyBoolYes;
501 else
502 m_move_to_nearest_code = eLazyBoolNo;
503
504 if (!success)
505 error.SetErrorStringWithFormat(
506 "Invalid boolean value for move-to-nearest-code option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000507 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000508 break;
509 }
510
511 case 'M':
512 m_func_names.push_back(option_arg);
513 m_func_name_type_mask |= eFunctionNameTypeMethod;
514 break;
515
516 case 'n':
517 m_func_names.push_back(option_arg);
518 m_func_name_type_mask |= eFunctionNameTypeAuto;
519 break;
520
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000521 case 'N': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000522 if (BreakpointID::StringIsBreakpointName(option_arg, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000524 else
525 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000526 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000527 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000528 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000529
530 case 'R': {
531 lldb::addr_t tmp_offset_addr;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000532 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
533 option_arg, 0, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000534 if (error.Success())
535 m_offset_addr = tmp_offset_addr;
536 } break;
537
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538 case 'O':
Zachary Turnerfe114832016-11-12 16:56:47 +0000539 m_exception_extra_args.AppendArgument("-O");
540 m_exception_extra_args.AppendArgument(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000541 break;
542
543 case 'p':
544 m_source_text_regexp.assign(option_arg);
545 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000546
547 case 'P':
548 m_python_class.assign(option_arg);
549 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000550
Kate Stoneb9c1b512016-09-06 20:57:50 +0000551 case 'r':
552 m_func_regexp.assign(option_arg);
553 break;
554
555 case 's':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000556 m_modules.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000557 break;
558
559 case 'S':
560 m_func_names.push_back(option_arg);
561 m_func_name_type_mask |= eFunctionNameTypeSelector;
562 break;
563
Jim Ingham3815e702018-09-13 21:35:32 +0000564 case 'v': {
565 if (!m_current_key.empty()) {
566 m_extra_args_sp->AddStringItem(m_current_key, option_arg);
567 m_current_key.clear();
568 }
569 else
570 error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
571 option_arg.str().c_str());
572 } break;
573
Kate Stoneb9c1b512016-09-06 20:57:50 +0000574 case 'w': {
575 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000576 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000577 if (!success)
578 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000579 "Invalid boolean value for on-throw option: '%s'",
580 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000581 } break;
582
Kate Stoneb9c1b512016-09-06 20:57:50 +0000583 case 'X':
584 m_source_regex_func_names.insert(option_arg);
585 break;
586
587 default:
588 error.SetErrorStringWithFormat("unrecognized option '%c'",
589 short_option);
590 break;
591 }
592
593 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000594 }
595
Kate Stoneb9c1b512016-09-06 20:57:50 +0000596 void OptionParsingStarting(ExecutionContext *execution_context) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000597 m_filenames.Clear();
598 m_line_num = 0;
599 m_column = 0;
600 m_func_names.clear();
601 m_func_name_type_mask = eFunctionNameTypeNone;
602 m_func_regexp.clear();
603 m_source_text_regexp.clear();
604 m_modules.Clear();
605 m_load_addr = LLDB_INVALID_ADDRESS;
606 m_offset_addr = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000607 m_catch_bp = false;
608 m_throw_bp = true;
609 m_hardware = false;
610 m_exception_language = eLanguageTypeUnknown;
611 m_language = lldb::eLanguageTypeUnknown;
612 m_skip_prologue = eLazyBoolCalculate;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000613 m_breakpoint_names.clear();
614 m_all_files = false;
615 m_exception_extra_args.Clear();
616 m_move_to_nearest_code = eLazyBoolCalculate;
617 m_source_regex_func_names.clear();
Jim Ingham3815e702018-09-13 21:35:32 +0000618 m_python_class.clear();
619 m_extra_args_sp.reset(new StructuredData::Dictionary());
620 m_current_key.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000621 }
622
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000623 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000624 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000625 }
Jim Ingham5a988412012-06-08 21:56:10 +0000626
Kate Stoneb9c1b512016-09-06 20:57:50 +0000627 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000628
Kate Stoneb9c1b512016-09-06 20:57:50 +0000629 std::string m_condition;
630 FileSpecList m_filenames;
631 uint32_t m_line_num;
632 uint32_t m_column;
633 std::vector<std::string> m_func_names;
634 std::vector<std::string> m_breakpoint_names;
Zachary Turner117b1fa2018-10-25 20:45:40 +0000635 lldb::FunctionNameType m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000636 std::string m_func_regexp;
637 std::string m_source_text_regexp;
638 FileSpecList m_modules;
639 lldb::addr_t m_load_addr;
640 lldb::addr_t m_offset_addr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000641 bool m_catch_bp;
642 bool m_throw_bp;
643 bool m_hardware; // Request to use hardware breakpoints
644 lldb::LanguageType m_exception_language;
645 lldb::LanguageType m_language;
646 LazyBool m_skip_prologue;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000647 bool m_all_files;
648 Args m_exception_extra_args;
649 LazyBool m_move_to_nearest_code;
650 std::unordered_set<std::string> m_source_regex_func_names;
Jim Ingham3815e702018-09-13 21:35:32 +0000651 std::string m_python_class;
652 StructuredData::DictionarySP m_extra_args_sp;
653 std::string m_current_key;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000654 };
Jim Ingham5a988412012-06-08 21:56:10 +0000655
656protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000657 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000658 Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000659
Kate Stoneb9c1b512016-09-06 20:57:50 +0000660 if (target == nullptr) {
661 result.AppendError("Invalid target. Must set target before setting "
662 "breakpoints (see 'target create' command).");
663 result.SetStatus(eReturnStatusFailed);
664 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000665 }
666
Kate Stoneb9c1b512016-09-06 20:57:50 +0000667 // The following are the various types of breakpoints that could be set:
668 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
669 // 2). -a [-s -g] (setting breakpoint by address)
670 // 3). -n [-s -g] (setting breakpoint by function name)
671 // 4). -r [-s -g] (setting breakpoint by function name regular
672 // expression)
673 // 5). -p -f (setting a breakpoint by comparing a reg-exp
674 // to source text)
675 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
676 // given language.)
677
678 BreakpointSetType break_type = eSetTypeInvalid;
679
Jim Ingham3815e702018-09-13 21:35:32 +0000680 if (!m_options.m_python_class.empty())
681 break_type = eSetTypeScripted;
682 else if (m_options.m_line_num != 0)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000683 break_type = eSetTypeFileAndLine;
684 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
685 break_type = eSetTypeAddress;
686 else if (!m_options.m_func_names.empty())
687 break_type = eSetTypeFunctionName;
688 else if (!m_options.m_func_regexp.empty())
689 break_type = eSetTypeFunctionRegexp;
690 else if (!m_options.m_source_text_regexp.empty())
691 break_type = eSetTypeSourceRegexp;
692 else if (m_options.m_exception_language != eLanguageTypeUnknown)
693 break_type = eSetTypeException;
694
Jim Inghamb842f2e2017-09-14 20:22:49 +0000695 BreakpointSP bp_sp = nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000696 FileSpec module_spec;
697 const bool internal = false;
698
699 // If the user didn't specify skip-prologue, having an offset should turn
700 // that off.
701 if (m_options.m_offset_addr != 0 &&
702 m_options.m_skip_prologue == eLazyBoolCalculate)
703 m_options.m_skip_prologue = eLazyBoolNo;
704
705 switch (break_type) {
706 case eSetTypeFileAndLine: // Breakpoint by source position
707 {
708 FileSpec file;
709 const size_t num_files = m_options.m_filenames.GetSize();
710 if (num_files == 0) {
711 if (!GetDefaultFile(target, file, result)) {
712 result.AppendError("No file supplied and no default file available.");
713 result.SetStatus(eReturnStatusFailed);
714 return false;
715 }
716 } else if (num_files > 1) {
717 result.AppendError("Only one file at a time is allowed for file and "
718 "line breakpoints.");
719 result.SetStatus(eReturnStatusFailed);
720 return false;
721 } else
722 file = m_options.m_filenames.GetFileSpecAtIndex(0);
723
724 // Only check for inline functions if
725 LazyBool check_inlines = eLazyBoolCalculate;
726
Jim Inghamb842f2e2017-09-14 20:22:49 +0000727 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
728 file,
Adrian Prantl431b1582018-08-30 15:11:00 +0000729 m_options.m_line_num,
730 m_options.m_column,
Jim Inghamb842f2e2017-09-14 20:22:49 +0000731 m_options.m_offset_addr,
732 check_inlines,
733 m_options.m_skip_prologue,
734 internal,
735 m_options.m_hardware,
736 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000737 } break;
738
739 case eSetTypeAddress: // Breakpoint by address
740 {
741 // If a shared library has been specified, make an lldb_private::Address
Jim Inghamb842f2e2017-09-14 20:22:49 +0000742 // with the library, and use that. That way the address breakpoint
743 // will track the load location of the library.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000744 size_t num_modules_specified = m_options.m_modules.GetSize();
745 if (num_modules_specified == 1) {
746 const FileSpec *file_spec =
747 m_options.m_modules.GetFileSpecPointerAtIndex(0);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000748 bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
749 internal, file_spec,
750 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000751 } else if (num_modules_specified == 0) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000752 bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
753 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000754 } else {
755 result.AppendError("Only one shared library can be specified for "
756 "address breakpoints.");
757 result.SetStatus(eReturnStatusFailed);
758 return false;
759 }
760 break;
761 }
762 case eSetTypeFunctionName: // Breakpoint by function name
763 {
Zachary Turner117b1fa2018-10-25 20:45:40 +0000764 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000765
766 if (name_type_mask == 0)
767 name_type_mask = eFunctionNameTypeAuto;
768
Jim Inghamb842f2e2017-09-14 20:22:49 +0000769 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
770 &(m_options.m_filenames),
771 m_options.m_func_names,
772 name_type_mask,
773 m_options.m_language,
774 m_options.m_offset_addr,
775 m_options.m_skip_prologue,
776 internal,
777 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000778 } break;
779
780 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
781 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000782 {
Zachary Turner95eae422016-09-21 16:01:28 +0000783 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000784 if (!regexp.IsValid()) {
785 char err_str[1024];
786 regexp.GetErrorAsCString(err_str, sizeof(err_str));
787 result.AppendErrorWithFormat(
788 "Function name regular expression could not be compiled: \"%s\"",
789 err_str);
790 result.SetStatus(eReturnStatusFailed);
791 return false;
792 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000793
Jim Inghamb842f2e2017-09-14 20:22:49 +0000794 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
795 &(m_options.m_filenames),
796 regexp,
797 m_options.m_language,
798 m_options.m_skip_prologue,
799 internal,
800 m_options.m_hardware);
Jim Inghame14dc262016-09-12 23:10:56 +0000801 }
802 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000803 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
804 {
805 const size_t num_files = m_options.m_filenames.GetSize();
806
807 if (num_files == 0 && !m_options.m_all_files) {
808 FileSpec file;
809 if (!GetDefaultFile(target, file, result)) {
810 result.AppendError(
811 "No files provided and could not find default file.");
812 result.SetStatus(eReturnStatusFailed);
813 return false;
814 } else {
815 m_options.m_filenames.Append(file);
816 }
817 }
818
Zachary Turner95eae422016-09-21 16:01:28 +0000819 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000820 if (!regexp.IsValid()) {
821 char err_str[1024];
822 regexp.GetErrorAsCString(err_str, sizeof(err_str));
823 result.AppendErrorWithFormat(
824 "Source text regular expression could not be compiled: \"%s\"",
825 err_str);
826 result.SetStatus(eReturnStatusFailed);
827 return false;
828 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000829 bp_sp =
830 target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
831 &(m_options.m_filenames),
832 m_options
833 .m_source_regex_func_names,
834 regexp,
835 internal,
836 m_options.m_hardware,
837 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000838 } break;
839 case eSetTypeException: {
Zachary Turner97206d52017-05-12 04:51:55 +0000840 Status precond_error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000841 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
842 m_options.m_catch_bp,
843 m_options.m_throw_bp,
844 internal,
845 &m_options
846 .m_exception_extra_args,
847 &precond_error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000848 if (precond_error.Fail()) {
849 result.AppendErrorWithFormat(
850 "Error setting extra exception arguments: %s",
851 precond_error.AsCString());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000852 target->RemoveBreakpointByID(bp_sp->GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000853 result.SetStatus(eReturnStatusFailed);
854 return false;
855 }
856 } break;
Jim Ingham3815e702018-09-13 21:35:32 +0000857 case eSetTypeScripted: {
858
859 Status error;
860 bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
861 &(m_options.m_modules),
862 &(m_options.m_filenames),
863 false,
864 m_options.m_hardware,
865 m_options.m_extra_args_sp,
866 &error);
867 if (error.Fail()) {
868 result.AppendErrorWithFormat(
869 "Error setting extra exception arguments: %s",
870 error.AsCString());
871 target->RemoveBreakpointByID(bp_sp->GetID());
872 result.SetStatus(eReturnStatusFailed);
873 return false;
874 }
875 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000876 default:
877 break;
878 }
879
880 // Now set the various options that were passed in:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000881 if (bp_sp) {
882 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000883
884 if (!m_options.m_breakpoint_names.empty()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000885 Status name_error;
Jim Inghamff9a91e2016-09-21 01:21:19 +0000886 for (auto name : m_options.m_breakpoint_names) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000887 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000888 if (name_error.Fail()) {
889 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
890 name.c_str());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000891 target->RemoveBreakpointByID(bp_sp->GetID());
Jim Inghamff9a91e2016-09-21 01:21:19 +0000892 result.SetStatus(eReturnStatusFailed);
893 return false;
894 }
895 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000896 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000897 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000898
899 if (bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000900 Stream &output_stream = result.GetOutputStream();
901 const bool show_locations = false;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000902 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000903 show_locations);
904 if (target == m_interpreter.GetDebugger().GetDummyTarget())
905 output_stream.Printf("Breakpoint set in dummy target, will get copied "
906 "into future targets.\n");
907 else {
Adrian Prantl05097242018-04-30 16:49:04 +0000908 // Don't print out this warning for exception breakpoints. They can
909 // get set before the target is set, but we won't know how to actually
910 // set the breakpoint till we run.
Jim Inghamb842f2e2017-09-14 20:22:49 +0000911 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000912 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
913 "actual locations.\n");
914 }
915 }
916 result.SetStatus(eReturnStatusSuccessFinishResult);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000917 } else if (!bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000918 result.AppendError("Breakpoint creation failed: No breakpoint created.");
919 result.SetStatus(eReturnStatusFailed);
920 }
921
922 return result.Succeeded();
923 }
924
Jim Ingham5a988412012-06-08 21:56:10 +0000925private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000926 bool GetDefaultFile(Target *target, FileSpec &file,
927 CommandReturnObject &result) {
928 uint32_t default_line;
Adrian Prantl05097242018-04-30 16:49:04 +0000929 // First use the Source Manager's default file. Then use the current stack
930 // frame's file.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000931 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
932 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
933 if (cur_frame == nullptr) {
934 result.AppendError(
935 "No selected frame to use to find the default file.");
936 result.SetStatus(eReturnStatusFailed);
937 return false;
938 } else if (!cur_frame->HasDebugInformation()) {
939 result.AppendError("Cannot use the selected frame to find the default "
940 "file, it has no debug info.");
941 result.SetStatus(eReturnStatusFailed);
942 return false;
943 } else {
944 const SymbolContext &sc =
945 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
946 if (sc.line_entry.file) {
947 file = sc.line_entry.file;
948 } else {
949 result.AppendError("Can't find the file for the selected frame to "
950 "use as the default file.");
951 result.SetStatus(eReturnStatusFailed);
952 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000953 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000954 }
Jim Ingham5a988412012-06-08 21:56:10 +0000955 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000956 return true;
957 }
958
Jim Inghamb842f2e2017-09-14 20:22:49 +0000959 BreakpointOptionGroup m_bp_opts;
960 BreakpointDummyOptionGroup m_dummy_options;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000961 CommandOptions m_options;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000962 OptionGroupOptions m_all_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000963};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000964
Jim Ingham5a988412012-06-08 21:56:10 +0000965//-------------------------------------------------------------------------
966// CommandObjectBreakpointModify
967//-------------------------------------------------------------------------
968#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000969
Kate Stoneb9c1b512016-09-06 20:57:50 +0000970class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000971public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000972 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
973 : CommandObjectParsed(interpreter, "breakpoint modify",
974 "Modify the options on a breakpoint or set of "
975 "breakpoints in the executable. "
976 "If no breakpoint is specified, acts on the last "
977 "created breakpoint. "
978 "With the exception of -e, -d and -i, passing an "
979 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000980 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000981 m_options() {
982 CommandArgumentEntry arg;
983 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
984 eArgTypeBreakpointIDRange);
985 // Add the entry for the first argument for this command to the object's
986 // arguments vector.
987 m_arguments.push_back(arg);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000988
989 m_options.Append(&m_bp_opts,
990 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
991 LLDB_OPT_SET_ALL);
992 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
993 m_options.Finalize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000994 }
995
996 ~CommandObjectBreakpointModify() override = default;
997
998 Options *GetOptions() override { return &m_options; }
999
Jim Ingham5a988412012-06-08 21:56:10 +00001000protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001001 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001002 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001003 if (target == nullptr) {
1004 result.AppendError("Invalid target. No existing target or breakpoints.");
1005 result.SetStatus(eReturnStatusFailed);
1006 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001007 }
1008
Kate Stoneb9c1b512016-09-06 20:57:50 +00001009 std::unique_lock<std::recursive_mutex> lock;
1010 target->GetBreakpointList().GetListMutex(lock);
1011
1012 BreakpointIDList valid_bp_ids;
1013
1014 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001015 command, target, result, &valid_bp_ids,
1016 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001017
1018 if (result.Succeeded()) {
1019 const size_t count = valid_bp_ids.GetSize();
1020 for (size_t i = 0; i < count; ++i) {
1021 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1022
1023 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1024 Breakpoint *bp =
1025 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1026 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1027 BreakpointLocation *location =
1028 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001029 if (location)
1030 location->GetLocationOptions()
1031 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001032 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001033 bp->GetOptions()
1034 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001035 }
1036 }
1037 }
1038 }
1039
1040 return result.Succeeded();
1041 }
1042
Jim Ingham5a988412012-06-08 21:56:10 +00001043private:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001044 BreakpointOptionGroup m_bp_opts;
1045 BreakpointDummyOptionGroup m_dummy_opts;
1046 OptionGroupOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001047};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001048
Jim Ingham5a988412012-06-08 21:56:10 +00001049//-------------------------------------------------------------------------
1050// CommandObjectBreakpointEnable
1051//-------------------------------------------------------------------------
1052#pragma mark Enable
1053
Kate Stoneb9c1b512016-09-06 20:57:50 +00001054class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001055public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001056 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1057 : CommandObjectParsed(interpreter, "enable",
1058 "Enable the specified disabled breakpoint(s). If "
1059 "no breakpoints are specified, enable all of them.",
1060 nullptr) {
1061 CommandArgumentEntry arg;
1062 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1063 eArgTypeBreakpointIDRange);
1064 // Add the entry for the first argument for this command to the object's
1065 // arguments vector.
1066 m_arguments.push_back(arg);
1067 }
Jim Ingham5a988412012-06-08 21:56:10 +00001068
Kate Stoneb9c1b512016-09-06 20:57:50 +00001069 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001070
1071protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001072 bool DoExecute(Args &command, CommandReturnObject &result) override {
1073 Target *target = GetSelectedOrDummyTarget();
1074 if (target == nullptr) {
1075 result.AppendError("Invalid target. No existing target or breakpoints.");
1076 result.SetStatus(eReturnStatusFailed);
1077 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001078 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001079
1080 std::unique_lock<std::recursive_mutex> lock;
1081 target->GetBreakpointList().GetListMutex(lock);
1082
1083 const BreakpointList &breakpoints = target->GetBreakpointList();
1084
1085 size_t num_breakpoints = breakpoints.GetSize();
1086
1087 if (num_breakpoints == 0) {
1088 result.AppendError("No breakpoints exist to be enabled.");
1089 result.SetStatus(eReturnStatusFailed);
1090 return false;
1091 }
1092
Zachary Turner11eb9c62016-10-05 20:03:37 +00001093 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001094 // No breakpoint selected; enable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001095 target->EnableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001096 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1097 " breakpoints)\n",
1098 (uint64_t)num_breakpoints);
1099 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1100 } else {
1101 // Particular breakpoint selected; enable that breakpoint.
1102 BreakpointIDList valid_bp_ids;
1103 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001104 command, target, result, &valid_bp_ids,
1105 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001106
1107 if (result.Succeeded()) {
1108 int enable_count = 0;
1109 int loc_count = 0;
1110 const size_t count = valid_bp_ids.GetSize();
1111 for (size_t i = 0; i < count; ++i) {
1112 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1113
1114 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1115 Breakpoint *breakpoint =
1116 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1117 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1118 BreakpointLocation *location =
1119 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1120 if (location) {
1121 location->SetEnabled(true);
1122 ++loc_count;
1123 }
1124 } else {
1125 breakpoint->SetEnabled(true);
1126 ++enable_count;
1127 }
1128 }
1129 }
1130 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1131 enable_count + loc_count);
1132 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1133 }
1134 }
1135
1136 return result.Succeeded();
1137 }
Jim Ingham5a988412012-06-08 21:56:10 +00001138};
1139
1140//-------------------------------------------------------------------------
1141// CommandObjectBreakpointDisable
1142//-------------------------------------------------------------------------
1143#pragma mark Disable
1144
Kate Stoneb9c1b512016-09-06 20:57:50 +00001145class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001146public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001147 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1148 : CommandObjectParsed(
1149 interpreter, "breakpoint disable",
1150 "Disable the specified breakpoint(s) without deleting "
1151 "them. If none are specified, disable all "
1152 "breakpoints.",
1153 nullptr) {
1154 SetHelpLong(
1155 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001156If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001157 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001158
Kate Stone7428a182016-07-14 22:03:10 +00001159)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001160 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001161regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001162 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001163
1164 (lldb) break disable 1
1165 (lldb) break enable 1.1
1166
1167execution will NOT stop at location 1.1. To achieve that, type:
1168
1169 (lldb) break disable 1.*
1170 (lldb) break enable 1.1
1171
Kate Stone7428a182016-07-14 22:03:10 +00001172)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001173 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001174the second re-enables the first location.");
1175
Kate Stoneb9c1b512016-09-06 20:57:50 +00001176 CommandArgumentEntry arg;
1177 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1178 eArgTypeBreakpointIDRange);
1179 // Add the entry for the first argument for this command to the object's
1180 // arguments vector.
1181 m_arguments.push_back(arg);
1182 }
Jim Ingham5a988412012-06-08 21:56:10 +00001183
Kate Stoneb9c1b512016-09-06 20:57:50 +00001184 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001185
1186protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001187 bool DoExecute(Args &command, CommandReturnObject &result) override {
1188 Target *target = GetSelectedOrDummyTarget();
1189 if (target == nullptr) {
1190 result.AppendError("Invalid target. No existing target or breakpoints.");
1191 result.SetStatus(eReturnStatusFailed);
1192 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001193 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001194
1195 std::unique_lock<std::recursive_mutex> lock;
1196 target->GetBreakpointList().GetListMutex(lock);
1197
1198 const BreakpointList &breakpoints = target->GetBreakpointList();
1199 size_t num_breakpoints = breakpoints.GetSize();
1200
1201 if (num_breakpoints == 0) {
1202 result.AppendError("No breakpoints exist to be disabled.");
1203 result.SetStatus(eReturnStatusFailed);
1204 return false;
1205 }
1206
Zachary Turner11eb9c62016-10-05 20:03:37 +00001207 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001208 // No breakpoint selected; disable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001209 target->DisableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001210 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1211 " breakpoints)\n",
1212 (uint64_t)num_breakpoints);
1213 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1214 } else {
1215 // Particular breakpoint selected; disable that breakpoint.
1216 BreakpointIDList valid_bp_ids;
1217
1218 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001219 command, target, result, &valid_bp_ids,
1220 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001221
1222 if (result.Succeeded()) {
1223 int disable_count = 0;
1224 int loc_count = 0;
1225 const size_t count = valid_bp_ids.GetSize();
1226 for (size_t i = 0; i < count; ++i) {
1227 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1228
1229 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1230 Breakpoint *breakpoint =
1231 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1232 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1233 BreakpointLocation *location =
1234 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1235 if (location) {
1236 location->SetEnabled(false);
1237 ++loc_count;
1238 }
1239 } else {
1240 breakpoint->SetEnabled(false);
1241 ++disable_count;
1242 }
1243 }
1244 }
1245 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1246 disable_count + loc_count);
1247 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1248 }
1249 }
1250
1251 return result.Succeeded();
1252 }
Jim Ingham5a988412012-06-08 21:56:10 +00001253};
1254
1255//-------------------------------------------------------------------------
1256// CommandObjectBreakpointList
1257//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001258
1259#pragma mark List::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001260static constexpr OptionDefinition g_breakpoint_list_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001261 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001262 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1263 { 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 +00001264 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1265 // But I need to see it for now, and don't want to wait.
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001266 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1267 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1268 { 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 +00001269 // clang-format on
1270};
1271
Jim Ingham5a988412012-06-08 21:56:10 +00001272#pragma mark List
1273
Kate Stoneb9c1b512016-09-06 20:57:50 +00001274class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001275public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001276 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1277 : CommandObjectParsed(
1278 interpreter, "breakpoint list",
1279 "List some or all breakpoints at configurable levels of detail.",
1280 nullptr),
1281 m_options() {
1282 CommandArgumentEntry arg;
1283 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001284
Kate Stoneb9c1b512016-09-06 20:57:50 +00001285 // Define the first (and only) variant of this arg.
1286 bp_id_arg.arg_type = eArgTypeBreakpointID;
1287 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001288
Kate Stoneb9c1b512016-09-06 20:57:50 +00001289 // There is only one variant this argument could be; put it into the
1290 // argument entry.
1291 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001292
Kate Stoneb9c1b512016-09-06 20:57:50 +00001293 // Push the data for the first argument into the m_arguments vector.
1294 m_arguments.push_back(arg);
1295 }
1296
1297 ~CommandObjectBreakpointList() override = default;
1298
1299 Options *GetOptions() override { return &m_options; }
1300
1301 class CommandOptions : public Options {
1302 public:
1303 CommandOptions()
1304 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001305 }
1306
Kate Stoneb9c1b512016-09-06 20:57:50 +00001307 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001308
Zachary Turner97206d52017-05-12 04:51:55 +00001309 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1310 ExecutionContext *execution_context) override {
1311 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001312 const int short_option = m_getopt_table[option_idx].val;
1313
1314 switch (short_option) {
1315 case 'b':
1316 m_level = lldb::eDescriptionLevelBrief;
1317 break;
1318 case 'D':
1319 m_use_dummy = true;
1320 break;
1321 case 'f':
1322 m_level = lldb::eDescriptionLevelFull;
1323 break;
1324 case 'v':
1325 m_level = lldb::eDescriptionLevelVerbose;
1326 break;
1327 case 'i':
1328 m_internal = true;
1329 break;
1330 default:
1331 error.SetErrorStringWithFormat("unrecognized option '%c'",
1332 short_option);
1333 break;
1334 }
1335
1336 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001337 }
Jim Ingham5a988412012-06-08 21:56:10 +00001338
Kate Stoneb9c1b512016-09-06 20:57:50 +00001339 void OptionParsingStarting(ExecutionContext *execution_context) override {
1340 m_level = lldb::eDescriptionLevelFull;
1341 m_internal = false;
1342 m_use_dummy = false;
1343 }
Jim Ingham5a988412012-06-08 21:56:10 +00001344
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001345 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001346 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001347 }
Jim Ingham5a988412012-06-08 21:56:10 +00001348
Kate Stoneb9c1b512016-09-06 20:57:50 +00001349 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001350
Kate Stoneb9c1b512016-09-06 20:57:50 +00001351 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001352
Kate Stoneb9c1b512016-09-06 20:57:50 +00001353 bool m_internal;
1354 bool m_use_dummy;
1355 };
Jim Ingham5a988412012-06-08 21:56:10 +00001356
1357protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001358 bool DoExecute(Args &command, CommandReturnObject &result) override {
1359 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001360
Kate Stoneb9c1b512016-09-06 20:57:50 +00001361 if (target == nullptr) {
1362 result.AppendError("Invalid target. No current target or breakpoints.");
1363 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1364 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001365 }
1366
Kate Stoneb9c1b512016-09-06 20:57:50 +00001367 const BreakpointList &breakpoints =
1368 target->GetBreakpointList(m_options.m_internal);
1369 std::unique_lock<std::recursive_mutex> lock;
1370 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1371
1372 size_t num_breakpoints = breakpoints.GetSize();
1373
1374 if (num_breakpoints == 0) {
1375 result.AppendMessage("No breakpoints currently set.");
1376 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1377 return true;
1378 }
1379
1380 Stream &output_stream = result.GetOutputStream();
1381
Zachary Turner11eb9c62016-10-05 20:03:37 +00001382 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001383 // No breakpoint selected; show info about all currently set breakpoints.
1384 result.AppendMessage("Current breakpoints:");
1385 for (size_t i = 0; i < num_breakpoints; ++i) {
1386 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001387 if (breakpoint->AllowList())
1388 AddBreakpointDescription(&output_stream, breakpoint,
1389 m_options.m_level);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001390 }
1391 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1392 } else {
1393 // Particular breakpoints selected; show info about that breakpoint.
1394 BreakpointIDList valid_bp_ids;
1395 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001396 command, target, result, &valid_bp_ids,
1397 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001398
1399 if (result.Succeeded()) {
1400 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1401 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1402 Breakpoint *breakpoint =
1403 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1404 AddBreakpointDescription(&output_stream, breakpoint,
1405 m_options.m_level);
1406 }
1407 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1408 } else {
1409 result.AppendError("Invalid breakpoint ID.");
1410 result.SetStatus(eReturnStatusFailed);
1411 }
1412 }
1413
1414 return result.Succeeded();
1415 }
1416
Jim Ingham5a988412012-06-08 21:56:10 +00001417private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001418 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001419};
1420
Jim Ingham5a988412012-06-08 21:56:10 +00001421//-------------------------------------------------------------------------
1422// CommandObjectBreakpointClear
1423//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001424#pragma mark Clear::CommandOptions
1425
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001426static constexpr OptionDefinition g_breakpoint_clear_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001427 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001428 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1429 { 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 +00001430 // clang-format on
1431};
1432
Jim Ingham5a988412012-06-08 21:56:10 +00001433#pragma mark Clear
1434
Kate Stoneb9c1b512016-09-06 20:57:50 +00001435class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001436public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001437 typedef enum BreakpointClearType {
1438 eClearTypeInvalid,
1439 eClearTypeFileAndLine
1440 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001441
Kate Stoneb9c1b512016-09-06 20:57:50 +00001442 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1443 : CommandObjectParsed(interpreter, "breakpoint clear",
1444 "Delete or disable breakpoints matching the "
1445 "specified source file and line.",
1446 "breakpoint clear <cmd-options>"),
1447 m_options() {}
1448
1449 ~CommandObjectBreakpointClear() override = default;
1450
1451 Options *GetOptions() override { return &m_options; }
1452
1453 class CommandOptions : public Options {
1454 public:
1455 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1456
1457 ~CommandOptions() override = default;
1458
Zachary Turner97206d52017-05-12 04:51:55 +00001459 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1460 ExecutionContext *execution_context) override {
1461 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001462 const int short_option = m_getopt_table[option_idx].val;
1463
1464 switch (short_option) {
1465 case 'f':
1466 m_filename.assign(option_arg);
1467 break;
1468
1469 case 'l':
Zachary Turnerfe114832016-11-12 16:56:47 +00001470 option_arg.getAsInteger(0, m_line_num);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001471 break;
1472
1473 default:
1474 error.SetErrorStringWithFormat("unrecognized option '%c'",
1475 short_option);
1476 break;
1477 }
1478
1479 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001480 }
1481
Kate Stoneb9c1b512016-09-06 20:57:50 +00001482 void OptionParsingStarting(ExecutionContext *execution_context) override {
1483 m_filename.clear();
1484 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001485 }
1486
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001487 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001488 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001489 }
Jim Ingham5a988412012-06-08 21:56:10 +00001490
Kate Stoneb9c1b512016-09-06 20:57:50 +00001491 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001492
Kate Stoneb9c1b512016-09-06 20:57:50 +00001493 std::string m_filename;
1494 uint32_t m_line_num;
1495 };
Jim Ingham5a988412012-06-08 21:56:10 +00001496
1497protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001498 bool DoExecute(Args &command, CommandReturnObject &result) override {
1499 Target *target = GetSelectedOrDummyTarget();
1500 if (target == nullptr) {
1501 result.AppendError("Invalid target. No existing target or breakpoints.");
1502 result.SetStatus(eReturnStatusFailed);
1503 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001504 }
1505
Adrian Prantl05097242018-04-30 16:49:04 +00001506 // The following are the various types of breakpoints that could be
1507 // cleared:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001508 // 1). -f -l (clearing breakpoint by source location)
1509
1510 BreakpointClearType break_type = eClearTypeInvalid;
1511
1512 if (m_options.m_line_num != 0)
1513 break_type = eClearTypeFileAndLine;
1514
1515 std::unique_lock<std::recursive_mutex> lock;
1516 target->GetBreakpointList().GetListMutex(lock);
1517
1518 BreakpointList &breakpoints = target->GetBreakpointList();
1519 size_t num_breakpoints = breakpoints.GetSize();
1520
1521 // Early return if there's no breakpoint at all.
1522 if (num_breakpoints == 0) {
1523 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1524 result.SetStatus(eReturnStatusFailed);
1525 return result.Succeeded();
1526 }
1527
1528 // Find matching breakpoints and delete them.
1529
1530 // First create a copy of all the IDs.
1531 std::vector<break_id_t> BreakIDs;
1532 for (size_t i = 0; i < num_breakpoints; ++i)
1533 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1534
1535 int num_cleared = 0;
1536 StreamString ss;
1537 switch (break_type) {
1538 case eClearTypeFileAndLine: // Breakpoint by source position
1539 {
1540 const ConstString filename(m_options.m_filename.c_str());
1541 BreakpointLocationCollection loc_coll;
1542
1543 for (size_t i = 0; i < num_breakpoints; ++i) {
1544 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1545
1546 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1547 // If the collection size is 0, it's a full match and we can just
1548 // remove the breakpoint.
1549 if (loc_coll.GetSize() == 0) {
1550 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1551 ss.EOL();
1552 target->RemoveBreakpointByID(bp->GetID());
1553 ++num_cleared;
1554 }
1555 }
1556 }
1557 } break;
1558
1559 default:
1560 break;
1561 }
1562
1563 if (num_cleared > 0) {
1564 Stream &output_stream = result.GetOutputStream();
1565 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
Zachary Turnerc1564272016-11-16 21:15:24 +00001566 output_stream << ss.GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001567 output_stream.EOL();
1568 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1569 } else {
1570 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1571 result.SetStatus(eReturnStatusFailed);
1572 }
1573
1574 return result.Succeeded();
1575 }
1576
Jim Ingham5a988412012-06-08 21:56:10 +00001577private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001578 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001579};
1580
Jim Ingham5a988412012-06-08 21:56:10 +00001581//-------------------------------------------------------------------------
1582// CommandObjectBreakpointDelete
1583//-------------------------------------------------------------------------
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001584static constexpr OptionDefinition g_breakpoint_delete_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001585 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001586 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1587 { 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 +00001588 // clang-format on
1589};
1590
Jim Ingham5a988412012-06-08 21:56:10 +00001591#pragma mark Delete
1592
Kate Stoneb9c1b512016-09-06 20:57:50 +00001593class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001594public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001595 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1596 : CommandObjectParsed(interpreter, "breakpoint delete",
1597 "Delete the specified breakpoint(s). If no "
1598 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001599 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001600 m_options() {
1601 CommandArgumentEntry arg;
1602 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1603 eArgTypeBreakpointIDRange);
1604 // Add the entry for the first argument for this command to the object's
1605 // arguments vector.
1606 m_arguments.push_back(arg);
1607 }
1608
1609 ~CommandObjectBreakpointDelete() override = default;
1610
1611 Options *GetOptions() override { return &m_options; }
1612
1613 class CommandOptions : public Options {
1614 public:
1615 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1616
1617 ~CommandOptions() override = default;
1618
Zachary Turner97206d52017-05-12 04:51:55 +00001619 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1620 ExecutionContext *execution_context) override {
1621 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001622 const int short_option = m_getopt_table[option_idx].val;
1623
1624 switch (short_option) {
1625 case 'f':
1626 m_force = true;
1627 break;
1628
1629 case 'D':
1630 m_use_dummy = true;
1631 break;
1632
1633 default:
1634 error.SetErrorStringWithFormat("unrecognized option '%c'",
1635 short_option);
1636 break;
1637 }
1638
1639 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001640 }
1641
Kate Stoneb9c1b512016-09-06 20:57:50 +00001642 void OptionParsingStarting(ExecutionContext *execution_context) override {
1643 m_use_dummy = false;
1644 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001645 }
1646
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001647 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001648 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001649 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001650
Kate Stoneb9c1b512016-09-06 20:57:50 +00001651 // Instance variables to hold the values for command options.
1652 bool m_use_dummy;
1653 bool m_force;
1654 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001655
Jim Ingham5a988412012-06-08 21:56:10 +00001656protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001657 bool DoExecute(Args &command, CommandReturnObject &result) override {
1658 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001659
Kate Stoneb9c1b512016-09-06 20:57:50 +00001660 if (target == nullptr) {
1661 result.AppendError("Invalid target. No existing target or breakpoints.");
1662 result.SetStatus(eReturnStatusFailed);
1663 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001664 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001665
Kate Stoneb9c1b512016-09-06 20:57:50 +00001666 std::unique_lock<std::recursive_mutex> lock;
1667 target->GetBreakpointList().GetListMutex(lock);
1668
1669 const BreakpointList &breakpoints = target->GetBreakpointList();
1670
1671 size_t num_breakpoints = breakpoints.GetSize();
1672
1673 if (num_breakpoints == 0) {
1674 result.AppendError("No breakpoints exist to be deleted.");
1675 result.SetStatus(eReturnStatusFailed);
1676 return false;
1677 }
1678
Zachary Turner11eb9c62016-10-05 20:03:37 +00001679 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001680 if (!m_options.m_force &&
1681 !m_interpreter.Confirm(
1682 "About to delete all breakpoints, do you want to do that?",
1683 true)) {
1684 result.AppendMessage("Operation cancelled...");
1685 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001686 target->RemoveAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001687 result.AppendMessageWithFormat(
1688 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1689 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1690 }
1691 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1692 } else {
1693 // Particular breakpoint selected; disable that breakpoint.
1694 BreakpointIDList valid_bp_ids;
1695 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001696 command, target, result, &valid_bp_ids,
1697 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001698
1699 if (result.Succeeded()) {
1700 int delete_count = 0;
1701 int disable_count = 0;
1702 const size_t count = valid_bp_ids.GetSize();
1703 for (size_t i = 0; i < count; ++i) {
1704 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1705
1706 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1707 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1708 Breakpoint *breakpoint =
1709 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1710 BreakpointLocation *location =
1711 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1712 // It makes no sense to try to delete individual locations, so we
1713 // disable them instead.
1714 if (location) {
1715 location->SetEnabled(false);
1716 ++disable_count;
1717 }
1718 } else {
1719 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1720 ++delete_count;
1721 }
1722 }
1723 }
1724 result.AppendMessageWithFormat(
1725 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1726 delete_count, disable_count);
1727 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1728 }
1729 }
1730 return result.Succeeded();
1731 }
1732
Jim Ingham33df7cd2014-12-06 01:28:03 +00001733private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001734 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001735};
1736
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001737//-------------------------------------------------------------------------
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001738// CommandObjectBreakpointName
1739//-------------------------------------------------------------------------
1740
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001741static constexpr OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001742 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001743 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1744 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1745 {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
1746 {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 +00001747 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001748};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001749class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001750public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001751 BreakpointNameOptionGroup()
1752 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1753 }
1754
1755 ~BreakpointNameOptionGroup() override = default;
1756
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001757 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001758 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001759 }
1760
Zachary Turner97206d52017-05-12 04:51:55 +00001761 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1762 ExecutionContext *execution_context) override {
1763 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001764 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1765
1766 switch (short_option) {
1767 case 'N':
Zachary Turnerfe114832016-11-12 16:56:47 +00001768 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001769 error.Success())
Zachary Turnerfe114832016-11-12 16:56:47 +00001770 m_name.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001771 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001772 case 'B':
Zachary Turnerfe114832016-11-12 16:56:47 +00001773 if (m_breakpoint.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001774 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001775 "unrecognized value \"%s\" for breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +00001776 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001777 break;
1778 case 'D':
Zachary Turnerfe114832016-11-12 16:56:47 +00001779 if (m_use_dummy.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001780 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001781 "unrecognized value \"%s\" for use-dummy",
Zachary Turnerfe114832016-11-12 16:56:47 +00001782 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001783 break;
Jim Inghame9632eb2017-09-15 00:52:35 +00001784 case 'H':
1785 m_help_string.SetValueFromString(option_arg);
1786 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001787
1788 default:
1789 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1790 short_option);
1791 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001792 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001793 return error;
1794 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001795
Kate Stoneb9c1b512016-09-06 20:57:50 +00001796 void OptionParsingStarting(ExecutionContext *execution_context) override {
1797 m_name.Clear();
1798 m_breakpoint.Clear();
1799 m_use_dummy.Clear();
1800 m_use_dummy.SetDefaultValue(false);
Jim Inghame9632eb2017-09-15 00:52:35 +00001801 m_help_string.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001802 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001803
Kate Stoneb9c1b512016-09-06 20:57:50 +00001804 OptionValueString m_name;
1805 OptionValueUInt64 m_breakpoint;
1806 OptionValueBoolean m_use_dummy;
Jim Inghame9632eb2017-09-15 00:52:35 +00001807 OptionValueString m_help_string;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001808};
1809
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001810static constexpr OptionDefinition g_breakpoint_access_options[] = {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001811 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001812 {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."},
1813 {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."},
1814 {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 +00001815 // clang-format on
1816};
1817
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001818class BreakpointAccessOptionGroup : public OptionGroup {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001819public:
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001820 BreakpointAccessOptionGroup() : OptionGroup() {}
1821
Jim Inghamb842f2e2017-09-14 20:22:49 +00001822 ~BreakpointAccessOptionGroup() override = default;
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001823
Jim Inghamb842f2e2017-09-14 20:22:49 +00001824 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1825 return llvm::makeArrayRef(g_breakpoint_access_options);
1826 }
1827 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1828 ExecutionContext *execution_context) override {
1829 Status error;
1830 const int short_option
1831 = g_breakpoint_access_options[option_idx].short_option;
1832
1833 switch (short_option) {
1834 case 'L': {
1835 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001836 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001837 if (success) {
1838 m_permissions.SetAllowList(value);
1839 } else
1840 error.SetErrorStringWithFormat(
1841 "invalid boolean value '%s' passed for -L option",
1842 option_arg.str().c_str());
1843 } break;
1844 case 'A': {
1845 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001846 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001847 if (success) {
1848 m_permissions.SetAllowDisable(value);
1849 } else
1850 error.SetErrorStringWithFormat(
1851 "invalid boolean value '%s' passed for -L option",
1852 option_arg.str().c_str());
1853 } break;
1854 case 'D': {
1855 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001856 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001857 if (success) {
1858 m_permissions.SetAllowDelete(value);
1859 } else
1860 error.SetErrorStringWithFormat(
1861 "invalid boolean value '%s' passed for -L option",
1862 option_arg.str().c_str());
1863 } break;
1864
1865 }
1866
1867 return error;
1868 }
1869
1870 void OptionParsingStarting(ExecutionContext *execution_context) override {
1871 }
1872
1873 const BreakpointName::Permissions &GetPermissions() const
1874 {
1875 return m_permissions;
1876 }
1877 BreakpointName::Permissions m_permissions;
1878};
1879
1880class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1881public:
1882 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1883 : CommandObjectParsed(
1884 interpreter, "configure", "Configure the options for the breakpoint"
1885 " name provided. "
1886 "If you provide a breakpoint id, the options will be copied from "
1887 "the breakpoint, otherwise only the options specified will be set "
1888 "on the name.",
1889 "breakpoint name configure <command-options> "
1890 "<breakpoint-name-list>"),
1891 m_bp_opts(), m_option_group() {
1892 // Create the first variant for the first (and only) argument for this
1893 // command.
1894 CommandArgumentEntry arg1;
1895 CommandArgumentData id_arg;
1896 id_arg.arg_type = eArgTypeBreakpointName;
1897 id_arg.arg_repetition = eArgRepeatOptional;
1898 arg1.push_back(id_arg);
1899 m_arguments.push_back(arg1);
1900
1901 m_option_group.Append(&m_bp_opts,
1902 LLDB_OPT_SET_ALL,
1903 LLDB_OPT_SET_1);
1904 m_option_group.Append(&m_access_options,
1905 LLDB_OPT_SET_ALL,
1906 LLDB_OPT_SET_ALL);
Jim Inghame9632eb2017-09-15 00:52:35 +00001907 m_option_group.Append(&m_bp_id,
1908 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1909 LLDB_OPT_SET_ALL);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001910 m_option_group.Finalize();
1911 }
1912
1913 ~CommandObjectBreakpointNameConfigure() override = default;
1914
1915 Options *GetOptions() override { return &m_option_group; }
1916
1917protected:
1918 bool DoExecute(Args &command, CommandReturnObject &result) override {
1919
1920 const size_t argc = command.GetArgumentCount();
1921 if (argc == 0) {
1922 result.AppendError("No names provided.");
1923 result.SetStatus(eReturnStatusFailed);
1924 return false;
1925 }
1926
1927 Target *target =
1928 GetSelectedOrDummyTarget(false);
1929
1930 if (target == nullptr) {
1931 result.AppendError("Invalid target. No existing target or breakpoints.");
1932 result.SetStatus(eReturnStatusFailed);
1933 return false;
1934 }
1935
1936 std::unique_lock<std::recursive_mutex> lock;
1937 target->GetBreakpointList().GetListMutex(lock);
1938
1939 // Make a pass through first to see that all the names are legal.
1940 for (auto &entry : command.entries()) {
1941 Status error;
1942 if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1943 {
1944 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1945 entry.c_str(), error.AsCString());
1946 result.SetStatus(eReturnStatusFailed);
1947 return false;
1948 }
1949 }
Adrian Prantl05097242018-04-30 16:49:04 +00001950 // Now configure them, we already pre-checked the names so we don't need to
1951 // check the error:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001952 BreakpointSP bp_sp;
1953 if (m_bp_id.m_breakpoint.OptionWasSet())
1954 {
1955 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1956 bp_sp = target->GetBreakpointByID(bp_id);
1957 if (!bp_sp)
1958 {
1959 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1960 bp_id);
1961 result.SetStatus(eReturnStatusFailed);
1962 return false;
1963 }
1964 }
1965
1966 Status error;
1967 for (auto &entry : command.entries()) {
1968 ConstString name(entry.c_str());
1969 BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1970 if (!bp_name)
1971 continue;
Jim Inghame9632eb2017-09-15 00:52:35 +00001972 if (m_bp_id.m_help_string.OptionWasSet())
1973 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1974
Jim Inghamb842f2e2017-09-14 20:22:49 +00001975 if (bp_sp)
1976 target->ConfigureBreakpointName(*bp_name,
1977 *bp_sp->GetOptions(),
1978 m_access_options.GetPermissions());
1979 else
1980 target->ConfigureBreakpointName(*bp_name,
1981 m_bp_opts.GetBreakpointOptions(),
1982 m_access_options.GetPermissions());
1983 }
1984 return true;
1985 }
1986
1987private:
1988 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1989 BreakpointOptionGroup m_bp_opts;
1990 BreakpointAccessOptionGroup m_access_options;
1991 OptionGroupOptions m_option_group;
1992};
1993
Kate Stoneb9c1b512016-09-06 20:57:50 +00001994class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001995public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001996 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1997 : CommandObjectParsed(
1998 interpreter, "add", "Add a name to the breakpoints provided.",
1999 "breakpoint name add <command-options> <breakpoint-id-list>"),
2000 m_name_options(), m_option_group() {
2001 // Create the first variant for the first (and only) argument for this
2002 // command.
2003 CommandArgumentEntry arg1;
2004 CommandArgumentData id_arg;
2005 id_arg.arg_type = eArgTypeBreakpointID;
2006 id_arg.arg_repetition = eArgRepeatOptional;
2007 arg1.push_back(id_arg);
2008 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002009
Kate Stoneb9c1b512016-09-06 20:57:50 +00002010 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2011 m_option_group.Finalize();
2012 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002013
Kate Stoneb9c1b512016-09-06 20:57:50 +00002014 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002015
Kate Stoneb9c1b512016-09-06 20:57:50 +00002016 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002017
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002018protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002019 bool DoExecute(Args &command, CommandReturnObject &result) override {
2020 if (!m_name_options.m_name.OptionWasSet()) {
2021 result.SetError("No name option provided.");
2022 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002023 }
2024
Kate Stoneb9c1b512016-09-06 20:57:50 +00002025 Target *target =
2026 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2027
2028 if (target == nullptr) {
2029 result.AppendError("Invalid target. No existing target or breakpoints.");
2030 result.SetStatus(eReturnStatusFailed);
2031 return false;
2032 }
2033
2034 std::unique_lock<std::recursive_mutex> lock;
2035 target->GetBreakpointList().GetListMutex(lock);
2036
2037 const BreakpointList &breakpoints = target->GetBreakpointList();
2038
2039 size_t num_breakpoints = breakpoints.GetSize();
2040 if (num_breakpoints == 0) {
2041 result.SetError("No breakpoints, cannot add names.");
2042 result.SetStatus(eReturnStatusFailed);
2043 return false;
2044 }
2045
2046 // Particular breakpoint selected; disable that breakpoint.
2047 BreakpointIDList valid_bp_ids;
2048 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002049 command, target, result, &valid_bp_ids,
2050 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002051
2052 if (result.Succeeded()) {
2053 if (valid_bp_ids.GetSize() == 0) {
2054 result.SetError("No breakpoints specified, cannot add names.");
2055 result.SetStatus(eReturnStatusFailed);
2056 return false;
2057 }
2058 size_t num_valid_ids = valid_bp_ids.GetSize();
Jim Inghamb842f2e2017-09-14 20:22:49 +00002059 const char *bp_name = m_name_options.m_name.GetCurrentValue();
2060 Status error; // This error reports illegal names, but we've already
2061 // checked that, so we don't need to check it again here.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002062 for (size_t index = 0; index < num_valid_ids; index++) {
2063 lldb::break_id_t bp_id =
2064 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2065 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002066 target->AddNameToBreakpoint(bp_sp, bp_name, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002067 }
2068 }
2069
2070 return true;
2071 }
2072
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002073private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002074 BreakpointNameOptionGroup m_name_options;
2075 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002076};
2077
Kate Stoneb9c1b512016-09-06 20:57:50 +00002078class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002079public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002080 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
2081 : CommandObjectParsed(
2082 interpreter, "delete",
2083 "Delete a name from the breakpoints provided.",
2084 "breakpoint name delete <command-options> <breakpoint-id-list>"),
2085 m_name_options(), m_option_group() {
2086 // Create the first variant for the first (and only) argument for this
2087 // command.
2088 CommandArgumentEntry arg1;
2089 CommandArgumentData id_arg;
2090 id_arg.arg_type = eArgTypeBreakpointID;
2091 id_arg.arg_repetition = eArgRepeatOptional;
2092 arg1.push_back(id_arg);
2093 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002094
Kate Stoneb9c1b512016-09-06 20:57:50 +00002095 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2096 m_option_group.Finalize();
2097 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002098
Kate Stoneb9c1b512016-09-06 20:57:50 +00002099 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002100
Kate Stoneb9c1b512016-09-06 20:57:50 +00002101 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002102
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002103protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002104 bool DoExecute(Args &command, CommandReturnObject &result) override {
2105 if (!m_name_options.m_name.OptionWasSet()) {
2106 result.SetError("No name option provided.");
2107 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002108 }
2109
Kate Stoneb9c1b512016-09-06 20:57:50 +00002110 Target *target =
2111 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2112
2113 if (target == nullptr) {
2114 result.AppendError("Invalid target. No existing target or breakpoints.");
2115 result.SetStatus(eReturnStatusFailed);
2116 return false;
2117 }
2118
2119 std::unique_lock<std::recursive_mutex> lock;
2120 target->GetBreakpointList().GetListMutex(lock);
2121
2122 const BreakpointList &breakpoints = target->GetBreakpointList();
2123
2124 size_t num_breakpoints = breakpoints.GetSize();
2125 if (num_breakpoints == 0) {
2126 result.SetError("No breakpoints, cannot delete names.");
2127 result.SetStatus(eReturnStatusFailed);
2128 return false;
2129 }
2130
2131 // Particular breakpoint selected; disable that breakpoint.
2132 BreakpointIDList valid_bp_ids;
2133 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002134 command, target, result, &valid_bp_ids,
2135 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002136
2137 if (result.Succeeded()) {
2138 if (valid_bp_ids.GetSize() == 0) {
2139 result.SetError("No breakpoints specified, cannot delete names.");
2140 result.SetStatus(eReturnStatusFailed);
2141 return false;
2142 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002143 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
Kate Stoneb9c1b512016-09-06 20:57:50 +00002144 size_t num_valid_ids = valid_bp_ids.GetSize();
2145 for (size_t index = 0; index < num_valid_ids; index++) {
2146 lldb::break_id_t bp_id =
2147 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2148 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002149 target->RemoveNameFromBreakpoint(bp_sp, bp_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002150 }
2151 }
2152
2153 return true;
2154 }
2155
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002156private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002157 BreakpointNameOptionGroup m_name_options;
2158 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002159};
2160
Kate Stoneb9c1b512016-09-06 20:57:50 +00002161class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002162public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002163 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2164 : CommandObjectParsed(interpreter, "list",
Jim Inghamb842f2e2017-09-14 20:22:49 +00002165 "List either the names for a breakpoint or info "
2166 "about a given name. With no arguments, lists all "
2167 "names",
Kate Stoneb9c1b512016-09-06 20:57:50 +00002168 "breakpoint name list <command-options>"),
2169 m_name_options(), m_option_group() {
Jim Inghamb842f2e2017-09-14 20:22:49 +00002170 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002171 m_option_group.Finalize();
2172 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002173
Kate Stoneb9c1b512016-09-06 20:57:50 +00002174 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002175
Kate Stoneb9c1b512016-09-06 20:57:50 +00002176 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002177
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002178protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002179 bool DoExecute(Args &command, CommandReturnObject &result) override {
2180 Target *target =
2181 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002182
Kate Stoneb9c1b512016-09-06 20:57:50 +00002183 if (target == nullptr) {
2184 result.AppendError("Invalid target. No existing target or breakpoints.");
2185 result.SetStatus(eReturnStatusFailed);
2186 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002187 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002188
2189
2190 std::vector<std::string> name_list;
2191 if (command.empty()) {
2192 target->GetBreakpointNames(name_list);
2193 } else {
2194 for (const Args::ArgEntry &arg : command)
2195 {
2196 name_list.push_back(arg.c_str());
2197 }
2198 }
2199
2200 if (name_list.empty()) {
2201 result.AppendMessage("No breakpoint names found.");
2202 } else {
2203 for (const std::string &name_str : name_list) {
2204 const char *name = name_str.c_str();
2205 // First print out the options for the name:
2206 Status error;
2207 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2208 false,
2209 error);
2210 if (bp_name)
2211 {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002212 StreamString s;
Jim Inghamb842f2e2017-09-14 20:22:49 +00002213 result.AppendMessageWithFormat("Name: %s\n", name);
2214 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2215 {
2216 result.AppendMessage(s.GetString());
2217 }
2218
2219 std::unique_lock<std::recursive_mutex> lock;
2220 target->GetBreakpointList().GetListMutex(lock);
2221
2222 BreakpointList &breakpoints = target->GetBreakpointList();
2223 bool any_set = false;
2224 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2225 if (bp_sp->MatchesName(name)) {
2226 StreamString s;
2227 any_set = true;
2228 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2229 s.EOL();
2230 result.AppendMessage(s.GetString());
2231 }
2232 }
2233 if (!any_set)
2234 result.AppendMessage("No breakpoints using this name.");
2235 } else {
2236 result.AppendMessageWithFormat("Name: %s not found.\n", name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002237 }
2238 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002239 }
2240 return true;
2241 }
2242
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002243private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002244 BreakpointNameOptionGroup m_name_options;
2245 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002246};
2247
2248//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002249// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002250//-------------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00002251class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002252public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002253 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2254 : CommandObjectMultiword(
2255 interpreter, "name", "Commands to manage name tags for breakpoints",
2256 "breakpoint name <subcommand> [<command-options>]") {
2257 CommandObjectSP add_command_object(
2258 new CommandObjectBreakpointNameAdd(interpreter));
2259 CommandObjectSP delete_command_object(
2260 new CommandObjectBreakpointNameDelete(interpreter));
2261 CommandObjectSP list_command_object(
2262 new CommandObjectBreakpointNameList(interpreter));
Jim Inghamb842f2e2017-09-14 20:22:49 +00002263 CommandObjectSP configure_command_object(
2264 new CommandObjectBreakpointNameConfigure(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002265
Kate Stoneb9c1b512016-09-06 20:57:50 +00002266 LoadSubCommand("add", add_command_object);
2267 LoadSubCommand("delete", delete_command_object);
2268 LoadSubCommand("list", list_command_object);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002269 LoadSubCommand("configure", configure_command_object);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002270 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002271
Kate Stoneb9c1b512016-09-06 20:57:50 +00002272 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002273};
2274
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002275//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002276// CommandObjectBreakpointRead
2277//-------------------------------------------------------------------------
Jim Ingham3acdf382016-09-22 22:20:28 +00002278#pragma mark Read::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002279static constexpr OptionDefinition g_breakpoint_read_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002280 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002281 {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2282 {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 +00002283 // clang-format on
2284};
2285
2286#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002287
2288class CommandObjectBreakpointRead : public CommandObjectParsed {
2289public:
2290 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2291 : CommandObjectParsed(interpreter, "breakpoint read",
2292 "Read and set the breakpoints previously saved to "
2293 "a file with \"breakpoint write\". ",
2294 nullptr),
2295 m_options() {
2296 CommandArgumentEntry arg;
2297 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2298 eArgTypeBreakpointIDRange);
2299 // Add the entry for the first argument for this command to the object's
2300 // arguments vector.
2301 m_arguments.push_back(arg);
2302 }
2303
2304 ~CommandObjectBreakpointRead() override = default;
2305
2306 Options *GetOptions() override { return &m_options; }
2307
2308 class CommandOptions : public Options {
2309 public:
2310 CommandOptions() : Options() {}
2311
2312 ~CommandOptions() override = default;
2313
Zachary Turner97206d52017-05-12 04:51:55 +00002314 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2315 ExecutionContext *execution_context) override {
2316 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002317 const int short_option = m_getopt_table[option_idx].val;
2318
2319 switch (short_option) {
2320 case 'f':
2321 m_filename.assign(option_arg);
2322 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002323 case 'N': {
Zachary Turner97206d52017-05-12 04:51:55 +00002324 Status name_error;
Jim Ingham3acdf382016-09-22 22:20:28 +00002325 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2326 name_error)) {
2327 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2328 name_error.AsCString());
2329 }
2330 m_names.push_back(option_arg);
2331 break;
2332 }
Jim Inghame14dc262016-09-12 23:10:56 +00002333 default:
2334 error.SetErrorStringWithFormat("unrecognized option '%c'",
2335 short_option);
2336 break;
2337 }
2338
2339 return error;
2340 }
2341
2342 void OptionParsingStarting(ExecutionContext *execution_context) override {
2343 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002344 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002345 }
2346
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002347 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002348 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002349 }
Jim Inghame14dc262016-09-12 23:10:56 +00002350
2351 // Instance variables to hold the values for command options.
2352
2353 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002354 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002355 };
2356
2357protected:
2358 bool DoExecute(Args &command, CommandReturnObject &result) override {
2359 Target *target = GetSelectedOrDummyTarget();
2360 if (target == nullptr) {
2361 result.AppendError("Invalid target. No existing target or breakpoints.");
2362 result.SetStatus(eReturnStatusFailed);
2363 return false;
2364 }
2365
Jim Ingham3acdf382016-09-22 22:20:28 +00002366 std::unique_lock<std::recursive_mutex> lock;
2367 target->GetBreakpointList().GetListMutex(lock);
2368
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002369 FileSpec input_spec(m_options.m_filename);
2370 FileSystem::Instance().Resolve(input_spec);
Jim Ingham01f16662016-09-14 19:07:35 +00002371 BreakpointIDList new_bps;
Zachary Turner97206d52017-05-12 04:51:55 +00002372 Status error = target->CreateBreakpointsFromFile(
2373 input_spec, m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002374
Jim Inghame14dc262016-09-12 23:10:56 +00002375 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002376 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002377 result.SetStatus(eReturnStatusFailed);
2378 return false;
2379 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002380
2381 Stream &output_stream = result.GetOutputStream();
2382
2383 size_t num_breakpoints = new_bps.GetSize();
2384 if (num_breakpoints == 0) {
2385 result.AppendMessage("No breakpoints added.");
2386 } else {
2387 // No breakpoint selected; show info about all currently set breakpoints.
2388 result.AppendMessage("New breakpoints:");
2389 for (size_t i = 0; i < num_breakpoints; ++i) {
2390 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2391 Breakpoint *bp = target->GetBreakpointList()
2392 .FindBreakpointByID(bp_id.GetBreakpointID())
2393 .get();
2394 if (bp)
2395 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2396 false);
2397 }
2398 }
Jim Inghame14dc262016-09-12 23:10:56 +00002399 return result.Succeeded();
2400 }
2401
2402private:
2403 CommandOptions m_options;
2404};
2405
Jim Inghame14dc262016-09-12 23:10:56 +00002406//-------------------------------------------------------------------------
2407// CommandObjectBreakpointWrite
2408//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002409#pragma mark Write::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002410static constexpr OptionDefinition g_breakpoint_write_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002411 // clang-format off
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002412 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2413 { 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 +00002414 // clang-format on
2415};
2416
2417#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002418class CommandObjectBreakpointWrite : public CommandObjectParsed {
2419public:
2420 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2421 : CommandObjectParsed(interpreter, "breakpoint write",
2422 "Write the breakpoints listed to a file that can "
2423 "be read in with \"breakpoint read\". "
2424 "If given no arguments, writes all breakpoints.",
2425 nullptr),
2426 m_options() {
2427 CommandArgumentEntry arg;
2428 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2429 eArgTypeBreakpointIDRange);
2430 // Add the entry for the first argument for this command to the object's
2431 // arguments vector.
2432 m_arguments.push_back(arg);
2433 }
2434
2435 ~CommandObjectBreakpointWrite() override = default;
2436
2437 Options *GetOptions() override { return &m_options; }
2438
2439 class CommandOptions : public Options {
2440 public:
2441 CommandOptions() : Options() {}
2442
2443 ~CommandOptions() override = default;
2444
Zachary Turner97206d52017-05-12 04:51:55 +00002445 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2446 ExecutionContext *execution_context) override {
2447 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002448 const int short_option = m_getopt_table[option_idx].val;
2449
2450 switch (short_option) {
2451 case 'f':
2452 m_filename.assign(option_arg);
2453 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002454 case 'a':
2455 m_append = true;
2456 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002457 default:
2458 error.SetErrorStringWithFormat("unrecognized option '%c'",
2459 short_option);
2460 break;
2461 }
2462
2463 return error;
2464 }
2465
2466 void OptionParsingStarting(ExecutionContext *execution_context) override {
2467 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002468 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002469 }
2470
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002471 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002472 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002473 }
Jim Inghame14dc262016-09-12 23:10:56 +00002474
2475 // Instance variables to hold the values for command options.
2476
2477 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002478 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002479 };
2480
2481protected:
2482 bool DoExecute(Args &command, CommandReturnObject &result) override {
2483 Target *target = GetSelectedOrDummyTarget();
2484 if (target == nullptr) {
2485 result.AppendError("Invalid target. No existing target or breakpoints.");
2486 result.SetStatus(eReturnStatusFailed);
2487 return false;
2488 }
2489
Jim Inghame14dc262016-09-12 23:10:56 +00002490 std::unique_lock<std::recursive_mutex> lock;
2491 target->GetBreakpointList().GetListMutex(lock);
2492
Jim Ingham01f16662016-09-14 19:07:35 +00002493 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002494 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002495 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002496 command, target, result, &valid_bp_ids,
2497 BreakpointName::Permissions::PermissionKinds::listPerm);
Jim Inghame14dc262016-09-12 23:10:56 +00002498
Jim Ingham01f16662016-09-14 19:07:35 +00002499 if (!result.Succeeded()) {
2500 result.SetStatus(eReturnStatusFailed);
2501 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002502 }
2503 }
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002504 FileSpec file_spec(m_options.m_filename);
2505 FileSystem::Instance().Resolve(file_spec);
2506 Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2507 m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002508 if (!error.Success()) {
2509 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2510 error.AsCString());
2511 result.SetStatus(eReturnStatusFailed);
2512 }
Jim Inghame14dc262016-09-12 23:10:56 +00002513 return result.Succeeded();
2514 }
2515
2516private:
2517 CommandOptions m_options;
2518};
2519
Jim Inghame14dc262016-09-12 23:10:56 +00002520//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002521// CommandObjectMultiwordBreakpoint
2522//-------------------------------------------------------------------------
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002523#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002524
Kate Stoneb9c1b512016-09-06 20:57:50 +00002525CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2526 CommandInterpreter &interpreter)
2527 : CommandObjectMultiword(
2528 interpreter, "breakpoint",
2529 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2530 "breakpoint <subcommand> [<command-options>]") {
2531 CommandObjectSP list_command_object(
2532 new CommandObjectBreakpointList(interpreter));
2533 CommandObjectSP enable_command_object(
2534 new CommandObjectBreakpointEnable(interpreter));
2535 CommandObjectSP disable_command_object(
2536 new CommandObjectBreakpointDisable(interpreter));
2537 CommandObjectSP clear_command_object(
2538 new CommandObjectBreakpointClear(interpreter));
2539 CommandObjectSP delete_command_object(
2540 new CommandObjectBreakpointDelete(interpreter));
2541 CommandObjectSP set_command_object(
2542 new CommandObjectBreakpointSet(interpreter));
2543 CommandObjectSP command_command_object(
2544 new CommandObjectBreakpointCommand(interpreter));
2545 CommandObjectSP modify_command_object(
2546 new CommandObjectBreakpointModify(interpreter));
2547 CommandObjectSP name_command_object(
2548 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002549 CommandObjectSP write_command_object(
2550 new CommandObjectBreakpointWrite(interpreter));
2551 CommandObjectSP read_command_object(
2552 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002553
Kate Stoneb9c1b512016-09-06 20:57:50 +00002554 list_command_object->SetCommandName("breakpoint list");
2555 enable_command_object->SetCommandName("breakpoint enable");
2556 disable_command_object->SetCommandName("breakpoint disable");
2557 clear_command_object->SetCommandName("breakpoint clear");
2558 delete_command_object->SetCommandName("breakpoint delete");
2559 set_command_object->SetCommandName("breakpoint set");
2560 command_command_object->SetCommandName("breakpoint command");
2561 modify_command_object->SetCommandName("breakpoint modify");
2562 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002563 write_command_object->SetCommandName("breakpoint write");
2564 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002565
Kate Stoneb9c1b512016-09-06 20:57:50 +00002566 LoadSubCommand("list", list_command_object);
2567 LoadSubCommand("enable", enable_command_object);
2568 LoadSubCommand("disable", disable_command_object);
2569 LoadSubCommand("clear", clear_command_object);
2570 LoadSubCommand("delete", delete_command_object);
2571 LoadSubCommand("set", set_command_object);
2572 LoadSubCommand("command", command_command_object);
2573 LoadSubCommand("modify", modify_command_object);
2574 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002575 LoadSubCommand("write", write_command_object);
2576 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002577}
2578
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002579CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002580
Kate Stoneb9c1b512016-09-06 20:57:50 +00002581void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2582 bool allow_locations,
2583 CommandReturnObject &result,
Jim Inghamb842f2e2017-09-14 20:22:49 +00002584 BreakpointIDList *valid_ids,
2585 BreakpointName::Permissions
2586 ::PermissionKinds
2587 purpose) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002588 // args can be strings representing 1). integers (for breakpoint ids)
2589 // 2). the full breakpoint & location
2590 // canonical representation
2591 // 3). the word "to" or a hyphen,
2592 // representing a range (in which case there
2593 // had *better* be an entry both before &
2594 // after of one of the first two types.
2595 // 4). A breakpoint name
2596 // If args is empty, we will use the last created breakpoint (if there is
2597 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002598
Kate Stoneb9c1b512016-09-06 20:57:50 +00002599 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002600
Zachary Turner11eb9c62016-10-05 20:03:37 +00002601 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002602 if (target->GetLastCreatedBreakpoint()) {
2603 valid_ids->AddBreakpointID(BreakpointID(
2604 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2605 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2606 } else {
2607 result.AppendError(
2608 "No breakpoint specified and no last created breakpoint.");
2609 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002610 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002611 return;
2612 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002613
Kate Stoneb9c1b512016-09-06 20:57:50 +00002614 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
Adrian Prantl05097242018-04-30 16:49:04 +00002615 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2616 // id range strings over; instead generate a list of strings for all the
2617 // breakpoint ids in the range, and shove all of those breakpoint id strings
2618 // into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002619
Jim Inghamb842f2e2017-09-14 20:22:49 +00002620 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2621 purpose, result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002622
Kate Stoneb9c1b512016-09-06 20:57:50 +00002623 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2624 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002625
Pavel Labath16662f32018-06-20 08:12:50 +00002626 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002627
Adrian Prantl05097242018-04-30 16:49:04 +00002628 // At this point, all of the breakpoint ids that the user passed in have
2629 // been converted to breakpoint IDs and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002630
Kate Stoneb9c1b512016-09-06 20:57:50 +00002631 if (result.Succeeded()) {
2632 // Now that we've converted everything from args into a list of breakpoint
Adrian Prantl05097242018-04-30 16:49:04 +00002633 // ids, go through our tentative list of breakpoint id's and verify that
2634 // they correspond to valid/currently set breakpoints.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002635
2636 const size_t count = valid_ids->GetSize();
2637 for (size_t i = 0; i < count; ++i) {
2638 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2639 Breakpoint *breakpoint =
2640 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2641 if (breakpoint != nullptr) {
2642 const size_t num_locations = breakpoint->GetNumLocations();
2643 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2644 StreamString id_str;
2645 BreakpointID::GetCanonicalReference(
2646 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2647 i = valid_ids->GetSize() + 1;
2648 result.AppendErrorWithFormat(
2649 "'%s' is not a currently valid breakpoint/location id.\n",
2650 id_str.GetData());
2651 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002652 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002653 } else {
2654 i = valid_ids->GetSize() + 1;
2655 result.AppendErrorWithFormat(
2656 "'%d' is not a currently valid breakpoint ID.\n",
2657 cur_bp_id.GetBreakpointID());
2658 result.SetStatus(eReturnStatusFailed);
2659 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002660 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002661 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002662}