blob: fb0553e482db94661c8b05efaa75d3898fb14411 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000012#include <vector>
13
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014// Other libraries and framework includes
15// Project includes
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000016#include "CommandObjectBreakpoint.h"
17#include "CommandObjectBreakpointCommand.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Breakpoint/Breakpoint.h"
19#include "lldb/Breakpoint/BreakpointIDList.h"
20#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000021#include "lldb/Host/OptionParser.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000022#include "lldb/Interpreter/CommandCompletions.h"
23#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/CommandReturnObject.h"
Pavel Labath47cbf4a2018-04-10 09:03:59 +000025#include "lldb/Interpreter/OptionArgParser.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000026#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000027#include "lldb/Interpreter/OptionValueString.h"
28#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000029#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000030#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000031#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000032#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000033#include "lldb/Target/Thread.h"
34#include "lldb/Target/ThreadSpec.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000035#include "lldb/Utility/RegularExpression.h"
36#include "lldb/Utility/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
38using namespace lldb;
39using namespace lldb_private;
40
Kate Stoneb9c1b512016-09-06 20:57:50 +000041static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
42 lldb::DescriptionLevel level) {
43 s->IndentMore();
44 bp->GetDescription(s, level, true);
45 s->IndentLess();
46 s->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047}
48
Jim Inghamb842f2e2017-09-14 20:22:49 +000049//-------------------------------------------------------------------------
50// Modifiable Breakpoint Options
51//-------------------------------------------------------------------------
52#pragma mark Modify::CommandOptions
53static OptionDefinition g_breakpoint_modify_options[] = {
54 // clang-format off
55 { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
56 { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
57 { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
58 { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
59 { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
60 { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." },
61 { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
62 { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." },
63 { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." },
64 { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." },
65 { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, 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." },
66 // clang-format on
67};
68class lldb_private::BreakpointOptionGroup : public OptionGroup
69{
70public:
71 BreakpointOptionGroup() :
72 OptionGroup(),
73 m_bp_opts(false) {}
74
75 ~BreakpointOptionGroup() override = default;
76
77 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
78 return llvm::makeArrayRef(g_breakpoint_modify_options);
79 }
80
81 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
82 ExecutionContext *execution_context) override {
83 Status error;
84 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
85
86 switch (short_option) {
87 case 'c':
Adrian Prantl05097242018-04-30 16:49:04 +000088 // Normally an empty breakpoint condition marks is as unset. But we need
89 // to say it was passed in.
Jim Inghamb842f2e2017-09-14 20:22:49 +000090 m_bp_opts.SetCondition(option_arg.str().c_str());
91 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
92 break;
93 case 'C':
94 m_commands.push_back(option_arg);
95 break;
96 case 'd':
97 m_bp_opts.SetEnabled(false);
98 break;
99 case 'e':
100 m_bp_opts.SetEnabled(true);
101 break;
102 case 'G': {
103 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000104 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000105 if (success) {
106 m_bp_opts.SetAutoContinue(value);
107 } else
108 error.SetErrorStringWithFormat(
109 "invalid boolean value '%s' passed for -G option",
110 option_arg.str().c_str());
111 }
112 break;
113 case 'i':
114 {
115 uint32_t ignore_count;
116 if (option_arg.getAsInteger(0, ignore_count))
117 error.SetErrorStringWithFormat("invalid ignore count '%s'",
118 option_arg.str().c_str());
119 else
120 m_bp_opts.SetIgnoreCount(ignore_count);
121 }
122 break;
123 case 'o': {
124 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000125 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000126 if (success) {
127 m_bp_opts.SetOneShot(value);
128 } else
129 error.SetErrorStringWithFormat(
130 "invalid boolean value '%s' passed for -o option",
131 option_arg.str().c_str());
132 } break;
133 case 't':
134 {
135 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
136 if (option_arg[0] != '\0') {
137 if (option_arg.getAsInteger(0, thread_id))
138 error.SetErrorStringWithFormat("invalid thread id string '%s'",
139 option_arg.str().c_str());
140 }
141 m_bp_opts.SetThreadID(thread_id);
142 }
143 break;
144 case 'T':
145 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
146 break;
147 case 'q':
148 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
149 break;
150 case 'x':
151 {
152 uint32_t thread_index = UINT32_MAX;
153 if (option_arg[0] != '\n') {
154 if (option_arg.getAsInteger(0, thread_index))
155 error.SetErrorStringWithFormat("invalid thread index string '%s'",
156 option_arg.str().c_str());
157 }
158 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
159 }
160 break;
161 default:
162 error.SetErrorStringWithFormat("unrecognized option '%c'",
163 short_option);
164 break;
165 }
166
167 return error;
168 }
169
170 void OptionParsingStarting(ExecutionContext *execution_context) override {
171 m_bp_opts.Clear();
172 m_commands.clear();
173 }
174
175 Status OptionParsingFinished(ExecutionContext *execution_context) override {
176 if (!m_commands.empty())
177 {
178 if (!m_commands.empty())
179 {
180 auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
181
182 for (std::string &str : m_commands)
183 cmd_data->user_source.AppendString(str);
184
185 cmd_data->stop_on_error = true;
186 m_bp_opts.SetCommandDataCallback(cmd_data);
187 }
188 }
189 return Status();
190 }
191
192 const BreakpointOptions &GetBreakpointOptions()
193 {
194 return m_bp_opts;
195 }
196
197 std::vector<std::string> m_commands;
198 BreakpointOptions m_bp_opts;
199
200};
201static OptionDefinition g_breakpoint_dummy_options[] = {
202 // clang-format off
203 { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, "
204 "which prime new targets." },
205 // clang-format on
206};
207
208class BreakpointDummyOptionGroup : public OptionGroup
209{
210public:
211 BreakpointDummyOptionGroup() :
212 OptionGroup() {}
213
214 ~BreakpointDummyOptionGroup() override = default;
215
216 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
217 return llvm::makeArrayRef(g_breakpoint_dummy_options);
218 }
219
220 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
221 ExecutionContext *execution_context) override {
222 Status error;
223 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
224
225 switch (short_option) {
226 case 'D':
227 m_use_dummy = true;
228 break;
229 default:
230 error.SetErrorStringWithFormat("unrecognized option '%c'",
231 short_option);
232 break;
233 }
234
235 return error;
236 }
237
238 void OptionParsingStarting(ExecutionContext *execution_context) override {
239 m_use_dummy = false;
240 }
241
242 bool m_use_dummy;
243
244};
245
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000246// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
247// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
248#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
249#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
250#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
251#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
252#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
253#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
254
255static OptionDefinition g_breakpoint_set_options[] = {
256 // clang-format off
257 { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option "
258 "multiple times to specify multiple shared libraries." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000259 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000260 { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default "
261 "lldb only looks for files that are #included if they use the standard include "
262 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
263 "#included, set target.inline-breakpoint-strategy to \"always\"." },
264 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
265
Adrian Prantl05097242018-04-30 16:49:04 +0000266 // Comment out this option for the moment, as we don't actually use it, but
267 // will in the future. This way users won't see it, but the infrastructure is
268 // left in place.
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000269 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
270 // "Set the breakpoint by source location at this particular column."},
271
272 { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to "
273 "a particular binary, then the address will be converted to a \"file\" "
274 "address, so that the breakpoint will track that binary+offset no matter where "
275 "the binary eventually loads. Alternately, if you also specify the module - "
276 "with the -s option - then the address will be treated as a file address in "
277 "that module, and resolved accordingly. Again, this will allow lldb to track "
278 "that offset on subsequent reloads. The module need not have been loaded at "
279 "the time you specify this breakpoint, and will get resolved when the module "
280 "is loaded." },
281 { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make "
282 "one breakpoint for multiple names" },
283 { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named "
284 "functions. Can be repeated multiple times." },
285 { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means "
Adrian Prantl4e8be2c2018-06-13 16:21:24 +0000286 "namespaces and all arguments, and for Objective-C this means a full function "
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000287 "prototype with class and selector. Can be repeated multiple times to make "
288 "one breakpoint for multiple names." },
289 { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to "
290 "make one breakpoint for multiple Selectors." },
291 { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to "
292 "make one breakpoint for multiple methods." },
293 { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find "
294 "the function name(s)." },
295 { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be "
296 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
297 "symbols." },
298 { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched "
299 "against the source text in a source file or files specified with the -f "
300 "option. The -f option can be specified more than once. If no source files "
301 "are specified, uses the current \"default source file\". If you want to "
302 "match against all source files, pass the \"--all-files\" option." },
303 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." },
304 { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without "
305 "options, on throw but not catch.)" },
306 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
307 { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
308
309 // Don't add this option till it actually does something useful...
310 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
311 // "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" },
312
313 { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
314 "(note: currently only implemented for setting breakpoints on identifiers). "
315 "If not set the target.language setting is used." },
316 { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. "
317 "If not set the target.skip-prologue setting is used." },
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000318 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
319 { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. "
320 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
321 { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code "
322 "setting is used." },
323 // clang-format on
324};
325
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000327// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000328//-------------------------------------------------------------------------
329
Kate Stoneb9c1b512016-09-06 20:57:50 +0000330class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000331public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000332 typedef enum BreakpointSetType {
333 eSetTypeInvalid,
334 eSetTypeFileAndLine,
335 eSetTypeAddress,
336 eSetTypeFunctionName,
337 eSetTypeFunctionRegexp,
338 eSetTypeSourceRegexp,
339 eSetTypeException
340 } 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':
437 m_filenames.AppendIfUnique(FileSpec(option_arg, false));
438 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;
457
Kate Stoneb9c1b512016-09-06 20:57:50 +0000458 case 'K': {
459 bool success;
460 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000461 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462 if (value)
463 m_skip_prologue = eLazyBoolYes;
464 else
465 m_skip_prologue = eLazyBoolNo;
466
467 if (!success)
468 error.SetErrorStringWithFormat(
469 "Invalid boolean value for skip prologue option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000470 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471 } break;
472
Zachary Turnerfe114832016-11-12 16:56:47 +0000473 case 'l':
474 if (option_arg.getAsInteger(0, m_line_num))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000475 error.SetErrorStringWithFormat("invalid line number: %s.",
Zachary Turnerfe114832016-11-12 16:56:47 +0000476 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000477 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000478
479 case 'L':
Zachary Turnerfe114832016-11-12 16:56:47 +0000480 m_language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481 if (m_language == eLanguageTypeUnknown)
482 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000483 "Unknown language type: '%s' for breakpoint",
484 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485 break;
486
487 case 'm': {
488 bool success;
489 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000490 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000491 if (value)
492 m_move_to_nearest_code = eLazyBoolYes;
493 else
494 m_move_to_nearest_code = eLazyBoolNo;
495
496 if (!success)
497 error.SetErrorStringWithFormat(
498 "Invalid boolean value for move-to-nearest-code option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000499 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000500 break;
501 }
502
503 case 'M':
504 m_func_names.push_back(option_arg);
505 m_func_name_type_mask |= eFunctionNameTypeMethod;
506 break;
507
508 case 'n':
509 m_func_names.push_back(option_arg);
510 m_func_name_type_mask |= eFunctionNameTypeAuto;
511 break;
512
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000513 case 'N': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000514 if (BreakpointID::StringIsBreakpointName(option_arg, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000515 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000516 else
517 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000518 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000520 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000521
522 case 'R': {
523 lldb::addr_t tmp_offset_addr;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000524 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
525 option_arg, 0, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000526 if (error.Success())
527 m_offset_addr = tmp_offset_addr;
528 } break;
529
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530 case 'O':
Zachary Turnerfe114832016-11-12 16:56:47 +0000531 m_exception_extra_args.AppendArgument("-O");
532 m_exception_extra_args.AppendArgument(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000533 break;
534
535 case 'p':
536 m_source_text_regexp.assign(option_arg);
537 break;
538
Kate Stoneb9c1b512016-09-06 20:57:50 +0000539 case 'r':
540 m_func_regexp.assign(option_arg);
541 break;
542
543 case 's':
544 m_modules.AppendIfUnique(FileSpec(option_arg, false));
545 break;
546
547 case 'S':
548 m_func_names.push_back(option_arg);
549 m_func_name_type_mask |= eFunctionNameTypeSelector;
550 break;
551
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552 case 'w': {
553 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000554 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555 if (!success)
556 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000557 "Invalid boolean value for on-throw option: '%s'",
558 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000559 } break;
560
Kate Stoneb9c1b512016-09-06 20:57:50 +0000561 case 'X':
562 m_source_regex_func_names.insert(option_arg);
563 break;
564
565 default:
566 error.SetErrorStringWithFormat("unrecognized option '%c'",
567 short_option);
568 break;
569 }
570
571 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000572 }
573
Kate Stoneb9c1b512016-09-06 20:57:50 +0000574 void OptionParsingStarting(ExecutionContext *execution_context) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000575 m_filenames.Clear();
576 m_line_num = 0;
577 m_column = 0;
578 m_func_names.clear();
579 m_func_name_type_mask = eFunctionNameTypeNone;
580 m_func_regexp.clear();
581 m_source_text_regexp.clear();
582 m_modules.Clear();
583 m_load_addr = LLDB_INVALID_ADDRESS;
584 m_offset_addr = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000585 m_catch_bp = false;
586 m_throw_bp = true;
587 m_hardware = false;
588 m_exception_language = eLanguageTypeUnknown;
589 m_language = lldb::eLanguageTypeUnknown;
590 m_skip_prologue = eLazyBoolCalculate;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000591 m_breakpoint_names.clear();
592 m_all_files = false;
593 m_exception_extra_args.Clear();
594 m_move_to_nearest_code = eLazyBoolCalculate;
595 m_source_regex_func_names.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000596 }
597
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000598 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000599 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000600 }
Jim Ingham5a988412012-06-08 21:56:10 +0000601
Kate Stoneb9c1b512016-09-06 20:57:50 +0000602 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000603
Kate Stoneb9c1b512016-09-06 20:57:50 +0000604 std::string m_condition;
605 FileSpecList m_filenames;
606 uint32_t m_line_num;
607 uint32_t m_column;
608 std::vector<std::string> m_func_names;
609 std::vector<std::string> m_breakpoint_names;
610 uint32_t m_func_name_type_mask;
611 std::string m_func_regexp;
612 std::string m_source_text_regexp;
613 FileSpecList m_modules;
614 lldb::addr_t m_load_addr;
615 lldb::addr_t m_offset_addr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000616 bool m_catch_bp;
617 bool m_throw_bp;
618 bool m_hardware; // Request to use hardware breakpoints
619 lldb::LanguageType m_exception_language;
620 lldb::LanguageType m_language;
621 LazyBool m_skip_prologue;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000622 bool m_all_files;
623 Args m_exception_extra_args;
624 LazyBool m_move_to_nearest_code;
625 std::unordered_set<std::string> m_source_regex_func_names;
626 };
Jim Ingham5a988412012-06-08 21:56:10 +0000627
628protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000629 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000630 Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000631
Kate Stoneb9c1b512016-09-06 20:57:50 +0000632 if (target == nullptr) {
633 result.AppendError("Invalid target. Must set target before setting "
634 "breakpoints (see 'target create' command).");
635 result.SetStatus(eReturnStatusFailed);
636 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000637 }
638
Kate Stoneb9c1b512016-09-06 20:57:50 +0000639 // The following are the various types of breakpoints that could be set:
640 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
641 // 2). -a [-s -g] (setting breakpoint by address)
642 // 3). -n [-s -g] (setting breakpoint by function name)
643 // 4). -r [-s -g] (setting breakpoint by function name regular
644 // expression)
645 // 5). -p -f (setting a breakpoint by comparing a reg-exp
646 // to source text)
647 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
648 // given language.)
649
650 BreakpointSetType break_type = eSetTypeInvalid;
651
652 if (m_options.m_line_num != 0)
653 break_type = eSetTypeFileAndLine;
654 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
655 break_type = eSetTypeAddress;
656 else if (!m_options.m_func_names.empty())
657 break_type = eSetTypeFunctionName;
658 else if (!m_options.m_func_regexp.empty())
659 break_type = eSetTypeFunctionRegexp;
660 else if (!m_options.m_source_text_regexp.empty())
661 break_type = eSetTypeSourceRegexp;
662 else if (m_options.m_exception_language != eLanguageTypeUnknown)
663 break_type = eSetTypeException;
664
Jim Inghamb842f2e2017-09-14 20:22:49 +0000665 BreakpointSP bp_sp = nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000666 FileSpec module_spec;
667 const bool internal = false;
668
669 // If the user didn't specify skip-prologue, having an offset should turn
670 // that off.
671 if (m_options.m_offset_addr != 0 &&
672 m_options.m_skip_prologue == eLazyBoolCalculate)
673 m_options.m_skip_prologue = eLazyBoolNo;
674
675 switch (break_type) {
676 case eSetTypeFileAndLine: // Breakpoint by source position
677 {
678 FileSpec file;
679 const size_t num_files = m_options.m_filenames.GetSize();
680 if (num_files == 0) {
681 if (!GetDefaultFile(target, file, result)) {
682 result.AppendError("No file supplied and no default file available.");
683 result.SetStatus(eReturnStatusFailed);
684 return false;
685 }
686 } else if (num_files > 1) {
687 result.AppendError("Only one file at a time is allowed for file and "
688 "line breakpoints.");
689 result.SetStatus(eReturnStatusFailed);
690 return false;
691 } else
692 file = m_options.m_filenames.GetFileSpecAtIndex(0);
693
694 // Only check for inline functions if
695 LazyBool check_inlines = eLazyBoolCalculate;
696
Jim Inghamb842f2e2017-09-14 20:22:49 +0000697 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
698 file,
699 m_options.m_line_num,
700 m_options.m_offset_addr,
701 check_inlines,
702 m_options.m_skip_prologue,
703 internal,
704 m_options.m_hardware,
705 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000706 } break;
707
708 case eSetTypeAddress: // Breakpoint by address
709 {
710 // If a shared library has been specified, make an lldb_private::Address
Jim Inghamb842f2e2017-09-14 20:22:49 +0000711 // with the library, and use that. That way the address breakpoint
712 // will track the load location of the library.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000713 size_t num_modules_specified = m_options.m_modules.GetSize();
714 if (num_modules_specified == 1) {
715 const FileSpec *file_spec =
716 m_options.m_modules.GetFileSpecPointerAtIndex(0);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000717 bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
718 internal, file_spec,
719 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000720 } else if (num_modules_specified == 0) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000721 bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
722 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000723 } else {
724 result.AppendError("Only one shared library can be specified for "
725 "address breakpoints.");
726 result.SetStatus(eReturnStatusFailed);
727 return false;
728 }
729 break;
730 }
731 case eSetTypeFunctionName: // Breakpoint by function name
732 {
733 uint32_t name_type_mask = m_options.m_func_name_type_mask;
734
735 if (name_type_mask == 0)
736 name_type_mask = eFunctionNameTypeAuto;
737
Jim Inghamb842f2e2017-09-14 20:22:49 +0000738 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
739 &(m_options.m_filenames),
740 m_options.m_func_names,
741 name_type_mask,
742 m_options.m_language,
743 m_options.m_offset_addr,
744 m_options.m_skip_prologue,
745 internal,
746 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000747 } break;
748
749 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
750 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000751 {
Zachary Turner95eae422016-09-21 16:01:28 +0000752 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000753 if (!regexp.IsValid()) {
754 char err_str[1024];
755 regexp.GetErrorAsCString(err_str, sizeof(err_str));
756 result.AppendErrorWithFormat(
757 "Function name regular expression could not be compiled: \"%s\"",
758 err_str);
759 result.SetStatus(eReturnStatusFailed);
760 return false;
761 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000762
Jim Inghamb842f2e2017-09-14 20:22:49 +0000763 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
764 &(m_options.m_filenames),
765 regexp,
766 m_options.m_language,
767 m_options.m_skip_prologue,
768 internal,
769 m_options.m_hardware);
Jim Inghame14dc262016-09-12 23:10:56 +0000770 }
771 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000772 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
773 {
774 const size_t num_files = m_options.m_filenames.GetSize();
775
776 if (num_files == 0 && !m_options.m_all_files) {
777 FileSpec file;
778 if (!GetDefaultFile(target, file, result)) {
779 result.AppendError(
780 "No files provided and could not find default file.");
781 result.SetStatus(eReturnStatusFailed);
782 return false;
783 } else {
784 m_options.m_filenames.Append(file);
785 }
786 }
787
Zachary Turner95eae422016-09-21 16:01:28 +0000788 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000789 if (!regexp.IsValid()) {
790 char err_str[1024];
791 regexp.GetErrorAsCString(err_str, sizeof(err_str));
792 result.AppendErrorWithFormat(
793 "Source text regular expression could not be compiled: \"%s\"",
794 err_str);
795 result.SetStatus(eReturnStatusFailed);
796 return false;
797 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000798 bp_sp =
799 target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
800 &(m_options.m_filenames),
801 m_options
802 .m_source_regex_func_names,
803 regexp,
804 internal,
805 m_options.m_hardware,
806 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000807 } break;
808 case eSetTypeException: {
Zachary Turner97206d52017-05-12 04:51:55 +0000809 Status precond_error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000810 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
811 m_options.m_catch_bp,
812 m_options.m_throw_bp,
813 internal,
814 &m_options
815 .m_exception_extra_args,
816 &precond_error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000817 if (precond_error.Fail()) {
818 result.AppendErrorWithFormat(
819 "Error setting extra exception arguments: %s",
820 precond_error.AsCString());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000821 target->RemoveBreakpointByID(bp_sp->GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000822 result.SetStatus(eReturnStatusFailed);
823 return false;
824 }
825 } break;
826 default:
827 break;
828 }
829
830 // Now set the various options that were passed in:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000831 if (bp_sp) {
832 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000833
834 if (!m_options.m_breakpoint_names.empty()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000835 Status name_error;
Jim Inghamff9a91e2016-09-21 01:21:19 +0000836 for (auto name : m_options.m_breakpoint_names) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000837 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000838 if (name_error.Fail()) {
839 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
840 name.c_str());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000841 target->RemoveBreakpointByID(bp_sp->GetID());
Jim Inghamff9a91e2016-09-21 01:21:19 +0000842 result.SetStatus(eReturnStatusFailed);
843 return false;
844 }
845 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000846 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000847 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000848
849 if (bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000850 Stream &output_stream = result.GetOutputStream();
851 const bool show_locations = false;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000852 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000853 show_locations);
854 if (target == m_interpreter.GetDebugger().GetDummyTarget())
855 output_stream.Printf("Breakpoint set in dummy target, will get copied "
856 "into future targets.\n");
857 else {
Adrian Prantl05097242018-04-30 16:49:04 +0000858 // Don't print out this warning for exception breakpoints. They can
859 // get set before the target is set, but we won't know how to actually
860 // set the breakpoint till we run.
Jim Inghamb842f2e2017-09-14 20:22:49 +0000861 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000862 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
863 "actual locations.\n");
864 }
865 }
866 result.SetStatus(eReturnStatusSuccessFinishResult);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000867 } else if (!bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000868 result.AppendError("Breakpoint creation failed: No breakpoint created.");
869 result.SetStatus(eReturnStatusFailed);
870 }
871
872 return result.Succeeded();
873 }
874
Jim Ingham5a988412012-06-08 21:56:10 +0000875private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000876 bool GetDefaultFile(Target *target, FileSpec &file,
877 CommandReturnObject &result) {
878 uint32_t default_line;
Adrian Prantl05097242018-04-30 16:49:04 +0000879 // First use the Source Manager's default file. Then use the current stack
880 // frame's file.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000881 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
882 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
883 if (cur_frame == nullptr) {
884 result.AppendError(
885 "No selected frame to use to find the default file.");
886 result.SetStatus(eReturnStatusFailed);
887 return false;
888 } else if (!cur_frame->HasDebugInformation()) {
889 result.AppendError("Cannot use the selected frame to find the default "
890 "file, it has no debug info.");
891 result.SetStatus(eReturnStatusFailed);
892 return false;
893 } else {
894 const SymbolContext &sc =
895 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
896 if (sc.line_entry.file) {
897 file = sc.line_entry.file;
898 } else {
899 result.AppendError("Can't find the file for the selected frame to "
900 "use as the default file.");
901 result.SetStatus(eReturnStatusFailed);
902 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000903 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000904 }
Jim Ingham5a988412012-06-08 21:56:10 +0000905 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000906 return true;
907 }
908
Jim Inghamb842f2e2017-09-14 20:22:49 +0000909 BreakpointOptionGroup m_bp_opts;
910 BreakpointDummyOptionGroup m_dummy_options;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000911 CommandOptions m_options;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000912 OptionGroupOptions m_all_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000913};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000914
Jim Ingham5a988412012-06-08 21:56:10 +0000915//-------------------------------------------------------------------------
916// CommandObjectBreakpointModify
917//-------------------------------------------------------------------------
918#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000919
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000921public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000922 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
923 : CommandObjectParsed(interpreter, "breakpoint modify",
924 "Modify the options on a breakpoint or set of "
925 "breakpoints in the executable. "
926 "If no breakpoint is specified, acts on the last "
927 "created breakpoint. "
928 "With the exception of -e, -d and -i, passing an "
929 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000930 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000931 m_options() {
932 CommandArgumentEntry arg;
933 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
934 eArgTypeBreakpointIDRange);
935 // Add the entry for the first argument for this command to the object's
936 // arguments vector.
937 m_arguments.push_back(arg);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000938
939 m_options.Append(&m_bp_opts,
940 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
941 LLDB_OPT_SET_ALL);
942 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
943 m_options.Finalize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000944 }
945
946 ~CommandObjectBreakpointModify() override = default;
947
948 Options *GetOptions() override { return &m_options; }
949
Jim Ingham5a988412012-06-08 21:56:10 +0000950protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000951 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000952 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000953 if (target == nullptr) {
954 result.AppendError("Invalid target. No existing target or breakpoints.");
955 result.SetStatus(eReturnStatusFailed);
956 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000957 }
958
Kate Stoneb9c1b512016-09-06 20:57:50 +0000959 std::unique_lock<std::recursive_mutex> lock;
960 target->GetBreakpointList().GetListMutex(lock);
961
962 BreakpointIDList valid_bp_ids;
963
964 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +0000965 command, target, result, &valid_bp_ids,
966 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000967
968 if (result.Succeeded()) {
969 const size_t count = valid_bp_ids.GetSize();
970 for (size_t i = 0; i < count; ++i) {
971 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
972
973 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
974 Breakpoint *bp =
975 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
976 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
977 BreakpointLocation *location =
978 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +0000979 if (location)
980 location->GetLocationOptions()
981 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000982 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000983 bp->GetOptions()
984 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000985 }
986 }
987 }
988 }
989
990 return result.Succeeded();
991 }
992
Jim Ingham5a988412012-06-08 21:56:10 +0000993private:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000994 BreakpointOptionGroup m_bp_opts;
995 BreakpointDummyOptionGroup m_dummy_opts;
996 OptionGroupOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000997};
Johnny Chen7d49c9c2012-05-25 21:10:46 +0000998
Jim Ingham5a988412012-06-08 21:56:10 +0000999//-------------------------------------------------------------------------
1000// CommandObjectBreakpointEnable
1001//-------------------------------------------------------------------------
1002#pragma mark Enable
1003
Kate Stoneb9c1b512016-09-06 20:57:50 +00001004class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001005public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001006 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1007 : CommandObjectParsed(interpreter, "enable",
1008 "Enable the specified disabled breakpoint(s). If "
1009 "no breakpoints are specified, enable all of them.",
1010 nullptr) {
1011 CommandArgumentEntry arg;
1012 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1013 eArgTypeBreakpointIDRange);
1014 // Add the entry for the first argument for this command to the object's
1015 // arguments vector.
1016 m_arguments.push_back(arg);
1017 }
Jim Ingham5a988412012-06-08 21:56:10 +00001018
Kate Stoneb9c1b512016-09-06 20:57:50 +00001019 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001020
1021protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001022 bool DoExecute(Args &command, CommandReturnObject &result) override {
1023 Target *target = GetSelectedOrDummyTarget();
1024 if (target == nullptr) {
1025 result.AppendError("Invalid target. No existing target or breakpoints.");
1026 result.SetStatus(eReturnStatusFailed);
1027 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001028 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001029
1030 std::unique_lock<std::recursive_mutex> lock;
1031 target->GetBreakpointList().GetListMutex(lock);
1032
1033 const BreakpointList &breakpoints = target->GetBreakpointList();
1034
1035 size_t num_breakpoints = breakpoints.GetSize();
1036
1037 if (num_breakpoints == 0) {
1038 result.AppendError("No breakpoints exist to be enabled.");
1039 result.SetStatus(eReturnStatusFailed);
1040 return false;
1041 }
1042
Zachary Turner11eb9c62016-10-05 20:03:37 +00001043 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001044 // No breakpoint selected; enable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001045 target->EnableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001046 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1047 " breakpoints)\n",
1048 (uint64_t)num_breakpoints);
1049 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1050 } else {
1051 // Particular breakpoint selected; enable that breakpoint.
1052 BreakpointIDList valid_bp_ids;
1053 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001054 command, target, result, &valid_bp_ids,
1055 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001056
1057 if (result.Succeeded()) {
1058 int enable_count = 0;
1059 int loc_count = 0;
1060 const size_t count = valid_bp_ids.GetSize();
1061 for (size_t i = 0; i < count; ++i) {
1062 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1063
1064 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1065 Breakpoint *breakpoint =
1066 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1067 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1068 BreakpointLocation *location =
1069 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1070 if (location) {
1071 location->SetEnabled(true);
1072 ++loc_count;
1073 }
1074 } else {
1075 breakpoint->SetEnabled(true);
1076 ++enable_count;
1077 }
1078 }
1079 }
1080 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1081 enable_count + loc_count);
1082 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1083 }
1084 }
1085
1086 return result.Succeeded();
1087 }
Jim Ingham5a988412012-06-08 21:56:10 +00001088};
1089
1090//-------------------------------------------------------------------------
1091// CommandObjectBreakpointDisable
1092//-------------------------------------------------------------------------
1093#pragma mark Disable
1094
Kate Stoneb9c1b512016-09-06 20:57:50 +00001095class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001096public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001097 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1098 : CommandObjectParsed(
1099 interpreter, "breakpoint disable",
1100 "Disable the specified breakpoint(s) without deleting "
1101 "them. If none are specified, disable all "
1102 "breakpoints.",
1103 nullptr) {
1104 SetHelpLong(
1105 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001106If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001107 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001108
Kate Stone7428a182016-07-14 22:03:10 +00001109)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001110 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001111regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001112 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001113
1114 (lldb) break disable 1
1115 (lldb) break enable 1.1
1116
1117execution will NOT stop at location 1.1. To achieve that, type:
1118
1119 (lldb) break disable 1.*
1120 (lldb) break enable 1.1
1121
Kate Stone7428a182016-07-14 22:03:10 +00001122)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001123 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001124the second re-enables the first location.");
1125
Kate Stoneb9c1b512016-09-06 20:57:50 +00001126 CommandArgumentEntry arg;
1127 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1128 eArgTypeBreakpointIDRange);
1129 // Add the entry for the first argument for this command to the object's
1130 // arguments vector.
1131 m_arguments.push_back(arg);
1132 }
Jim Ingham5a988412012-06-08 21:56:10 +00001133
Kate Stoneb9c1b512016-09-06 20:57:50 +00001134 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001135
1136protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001137 bool DoExecute(Args &command, CommandReturnObject &result) override {
1138 Target *target = GetSelectedOrDummyTarget();
1139 if (target == nullptr) {
1140 result.AppendError("Invalid target. No existing target or breakpoints.");
1141 result.SetStatus(eReturnStatusFailed);
1142 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001143 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001144
1145 std::unique_lock<std::recursive_mutex> lock;
1146 target->GetBreakpointList().GetListMutex(lock);
1147
1148 const BreakpointList &breakpoints = target->GetBreakpointList();
1149 size_t num_breakpoints = breakpoints.GetSize();
1150
1151 if (num_breakpoints == 0) {
1152 result.AppendError("No breakpoints exist to be disabled.");
1153 result.SetStatus(eReturnStatusFailed);
1154 return false;
1155 }
1156
Zachary Turner11eb9c62016-10-05 20:03:37 +00001157 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001158 // No breakpoint selected; disable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001159 target->DisableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001160 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1161 " breakpoints)\n",
1162 (uint64_t)num_breakpoints);
1163 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1164 } else {
1165 // Particular breakpoint selected; disable that breakpoint.
1166 BreakpointIDList valid_bp_ids;
1167
1168 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001169 command, target, result, &valid_bp_ids,
1170 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001171
1172 if (result.Succeeded()) {
1173 int disable_count = 0;
1174 int loc_count = 0;
1175 const size_t count = valid_bp_ids.GetSize();
1176 for (size_t i = 0; i < count; ++i) {
1177 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1178
1179 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1180 Breakpoint *breakpoint =
1181 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1182 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1183 BreakpointLocation *location =
1184 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1185 if (location) {
1186 location->SetEnabled(false);
1187 ++loc_count;
1188 }
1189 } else {
1190 breakpoint->SetEnabled(false);
1191 ++disable_count;
1192 }
1193 }
1194 }
1195 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1196 disable_count + loc_count);
1197 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1198 }
1199 }
1200
1201 return result.Succeeded();
1202 }
Jim Ingham5a988412012-06-08 21:56:10 +00001203};
1204
1205//-------------------------------------------------------------------------
1206// CommandObjectBreakpointList
1207//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001208
1209#pragma mark List::CommandOptions
1210static OptionDefinition g_breakpoint_list_options[] = {
1211 // clang-format off
1212 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1213 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
1214 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1215 // But I need to see it for now, and don't want to wait.
1216 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1217 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1218 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
1219 // clang-format on
1220};
1221
Jim Ingham5a988412012-06-08 21:56:10 +00001222#pragma mark List
1223
Kate Stoneb9c1b512016-09-06 20:57:50 +00001224class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001225public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001226 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1227 : CommandObjectParsed(
1228 interpreter, "breakpoint list",
1229 "List some or all breakpoints at configurable levels of detail.",
1230 nullptr),
1231 m_options() {
1232 CommandArgumentEntry arg;
1233 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001234
Kate Stoneb9c1b512016-09-06 20:57:50 +00001235 // Define the first (and only) variant of this arg.
1236 bp_id_arg.arg_type = eArgTypeBreakpointID;
1237 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001238
Kate Stoneb9c1b512016-09-06 20:57:50 +00001239 // There is only one variant this argument could be; put it into the
1240 // argument entry.
1241 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001242
Kate Stoneb9c1b512016-09-06 20:57:50 +00001243 // Push the data for the first argument into the m_arguments vector.
1244 m_arguments.push_back(arg);
1245 }
1246
1247 ~CommandObjectBreakpointList() override = default;
1248
1249 Options *GetOptions() override { return &m_options; }
1250
1251 class CommandOptions : public Options {
1252 public:
1253 CommandOptions()
1254 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001255 }
1256
Kate Stoneb9c1b512016-09-06 20:57:50 +00001257 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001258
Zachary Turner97206d52017-05-12 04:51:55 +00001259 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1260 ExecutionContext *execution_context) override {
1261 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001262 const int short_option = m_getopt_table[option_idx].val;
1263
1264 switch (short_option) {
1265 case 'b':
1266 m_level = lldb::eDescriptionLevelBrief;
1267 break;
1268 case 'D':
1269 m_use_dummy = true;
1270 break;
1271 case 'f':
1272 m_level = lldb::eDescriptionLevelFull;
1273 break;
1274 case 'v':
1275 m_level = lldb::eDescriptionLevelVerbose;
1276 break;
1277 case 'i':
1278 m_internal = true;
1279 break;
1280 default:
1281 error.SetErrorStringWithFormat("unrecognized option '%c'",
1282 short_option);
1283 break;
1284 }
1285
1286 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001287 }
Jim Ingham5a988412012-06-08 21:56:10 +00001288
Kate Stoneb9c1b512016-09-06 20:57:50 +00001289 void OptionParsingStarting(ExecutionContext *execution_context) override {
1290 m_level = lldb::eDescriptionLevelFull;
1291 m_internal = false;
1292 m_use_dummy = false;
1293 }
Jim Ingham5a988412012-06-08 21:56:10 +00001294
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001295 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001296 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001297 }
Jim Ingham5a988412012-06-08 21:56:10 +00001298
Kate Stoneb9c1b512016-09-06 20:57:50 +00001299 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001300
Kate Stoneb9c1b512016-09-06 20:57:50 +00001301 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001302
Kate Stoneb9c1b512016-09-06 20:57:50 +00001303 bool m_internal;
1304 bool m_use_dummy;
1305 };
Jim Ingham5a988412012-06-08 21:56:10 +00001306
1307protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001308 bool DoExecute(Args &command, CommandReturnObject &result) override {
1309 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001310
Kate Stoneb9c1b512016-09-06 20:57:50 +00001311 if (target == nullptr) {
1312 result.AppendError("Invalid target. No current target or breakpoints.");
1313 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1314 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001315 }
1316
Kate Stoneb9c1b512016-09-06 20:57:50 +00001317 const BreakpointList &breakpoints =
1318 target->GetBreakpointList(m_options.m_internal);
1319 std::unique_lock<std::recursive_mutex> lock;
1320 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1321
1322 size_t num_breakpoints = breakpoints.GetSize();
1323
1324 if (num_breakpoints == 0) {
1325 result.AppendMessage("No breakpoints currently set.");
1326 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1327 return true;
1328 }
1329
1330 Stream &output_stream = result.GetOutputStream();
1331
Zachary Turner11eb9c62016-10-05 20:03:37 +00001332 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001333 // No breakpoint selected; show info about all currently set breakpoints.
1334 result.AppendMessage("Current breakpoints:");
1335 for (size_t i = 0; i < num_breakpoints; ++i) {
1336 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001337 if (breakpoint->AllowList())
1338 AddBreakpointDescription(&output_stream, breakpoint,
1339 m_options.m_level);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001340 }
1341 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1342 } else {
1343 // Particular breakpoints selected; show info about that breakpoint.
1344 BreakpointIDList valid_bp_ids;
1345 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001346 command, target, result, &valid_bp_ids,
1347 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001348
1349 if (result.Succeeded()) {
1350 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1351 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1352 Breakpoint *breakpoint =
1353 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1354 AddBreakpointDescription(&output_stream, breakpoint,
1355 m_options.m_level);
1356 }
1357 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1358 } else {
1359 result.AppendError("Invalid breakpoint ID.");
1360 result.SetStatus(eReturnStatusFailed);
1361 }
1362 }
1363
1364 return result.Succeeded();
1365 }
1366
Jim Ingham5a988412012-06-08 21:56:10 +00001367private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001368 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001369};
1370
Jim Ingham5a988412012-06-08 21:56:10 +00001371//-------------------------------------------------------------------------
1372// CommandObjectBreakpointClear
1373//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001374#pragma mark Clear::CommandOptions
1375
1376static OptionDefinition g_breakpoint_clear_options[] = {
1377 // clang-format off
1378 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1379 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
1380 // clang-format on
1381};
1382
Jim Ingham5a988412012-06-08 21:56:10 +00001383#pragma mark Clear
1384
Kate Stoneb9c1b512016-09-06 20:57:50 +00001385class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001386public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001387 typedef enum BreakpointClearType {
1388 eClearTypeInvalid,
1389 eClearTypeFileAndLine
1390 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001391
Kate Stoneb9c1b512016-09-06 20:57:50 +00001392 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1393 : CommandObjectParsed(interpreter, "breakpoint clear",
1394 "Delete or disable breakpoints matching the "
1395 "specified source file and line.",
1396 "breakpoint clear <cmd-options>"),
1397 m_options() {}
1398
1399 ~CommandObjectBreakpointClear() override = default;
1400
1401 Options *GetOptions() override { return &m_options; }
1402
1403 class CommandOptions : public Options {
1404 public:
1405 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1406
1407 ~CommandOptions() override = default;
1408
Zachary Turner97206d52017-05-12 04:51:55 +00001409 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1410 ExecutionContext *execution_context) override {
1411 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001412 const int short_option = m_getopt_table[option_idx].val;
1413
1414 switch (short_option) {
1415 case 'f':
1416 m_filename.assign(option_arg);
1417 break;
1418
1419 case 'l':
Zachary Turnerfe114832016-11-12 16:56:47 +00001420 option_arg.getAsInteger(0, m_line_num);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001421 break;
1422
1423 default:
1424 error.SetErrorStringWithFormat("unrecognized option '%c'",
1425 short_option);
1426 break;
1427 }
1428
1429 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001430 }
1431
Kate Stoneb9c1b512016-09-06 20:57:50 +00001432 void OptionParsingStarting(ExecutionContext *execution_context) override {
1433 m_filename.clear();
1434 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001435 }
1436
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001437 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001438 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001439 }
Jim Ingham5a988412012-06-08 21:56:10 +00001440
Kate Stoneb9c1b512016-09-06 20:57:50 +00001441 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001442
Kate Stoneb9c1b512016-09-06 20:57:50 +00001443 std::string m_filename;
1444 uint32_t m_line_num;
1445 };
Jim Ingham5a988412012-06-08 21:56:10 +00001446
1447protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001448 bool DoExecute(Args &command, CommandReturnObject &result) override {
1449 Target *target = GetSelectedOrDummyTarget();
1450 if (target == nullptr) {
1451 result.AppendError("Invalid target. No existing target or breakpoints.");
1452 result.SetStatus(eReturnStatusFailed);
1453 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001454 }
1455
Adrian Prantl05097242018-04-30 16:49:04 +00001456 // The following are the various types of breakpoints that could be
1457 // cleared:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001458 // 1). -f -l (clearing breakpoint by source location)
1459
1460 BreakpointClearType break_type = eClearTypeInvalid;
1461
1462 if (m_options.m_line_num != 0)
1463 break_type = eClearTypeFileAndLine;
1464
1465 std::unique_lock<std::recursive_mutex> lock;
1466 target->GetBreakpointList().GetListMutex(lock);
1467
1468 BreakpointList &breakpoints = target->GetBreakpointList();
1469 size_t num_breakpoints = breakpoints.GetSize();
1470
1471 // Early return if there's no breakpoint at all.
1472 if (num_breakpoints == 0) {
1473 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1474 result.SetStatus(eReturnStatusFailed);
1475 return result.Succeeded();
1476 }
1477
1478 // Find matching breakpoints and delete them.
1479
1480 // First create a copy of all the IDs.
1481 std::vector<break_id_t> BreakIDs;
1482 for (size_t i = 0; i < num_breakpoints; ++i)
1483 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1484
1485 int num_cleared = 0;
1486 StreamString ss;
1487 switch (break_type) {
1488 case eClearTypeFileAndLine: // Breakpoint by source position
1489 {
1490 const ConstString filename(m_options.m_filename.c_str());
1491 BreakpointLocationCollection loc_coll;
1492
1493 for (size_t i = 0; i < num_breakpoints; ++i) {
1494 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1495
1496 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1497 // If the collection size is 0, it's a full match and we can just
1498 // remove the breakpoint.
1499 if (loc_coll.GetSize() == 0) {
1500 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1501 ss.EOL();
1502 target->RemoveBreakpointByID(bp->GetID());
1503 ++num_cleared;
1504 }
1505 }
1506 }
1507 } break;
1508
1509 default:
1510 break;
1511 }
1512
1513 if (num_cleared > 0) {
1514 Stream &output_stream = result.GetOutputStream();
1515 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
Zachary Turnerc1564272016-11-16 21:15:24 +00001516 output_stream << ss.GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001517 output_stream.EOL();
1518 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1519 } else {
1520 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1521 result.SetStatus(eReturnStatusFailed);
1522 }
1523
1524 return result.Succeeded();
1525 }
1526
Jim Ingham5a988412012-06-08 21:56:10 +00001527private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001528 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001529};
1530
Jim Ingham5a988412012-06-08 21:56:10 +00001531//-------------------------------------------------------------------------
1532// CommandObjectBreakpointDelete
1533//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001534static OptionDefinition g_breakpoint_delete_options[] = {
1535 // clang-format off
1536 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1537 { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
1538 // clang-format on
1539};
1540
Jim Ingham5a988412012-06-08 21:56:10 +00001541#pragma mark Delete
1542
Kate Stoneb9c1b512016-09-06 20:57:50 +00001543class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001544public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001545 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1546 : CommandObjectParsed(interpreter, "breakpoint delete",
1547 "Delete the specified breakpoint(s). If no "
1548 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001549 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001550 m_options() {
1551 CommandArgumentEntry arg;
1552 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1553 eArgTypeBreakpointIDRange);
1554 // Add the entry for the first argument for this command to the object's
1555 // arguments vector.
1556 m_arguments.push_back(arg);
1557 }
1558
1559 ~CommandObjectBreakpointDelete() override = default;
1560
1561 Options *GetOptions() override { return &m_options; }
1562
1563 class CommandOptions : public Options {
1564 public:
1565 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1566
1567 ~CommandOptions() override = default;
1568
Zachary Turner97206d52017-05-12 04:51:55 +00001569 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1570 ExecutionContext *execution_context) override {
1571 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001572 const int short_option = m_getopt_table[option_idx].val;
1573
1574 switch (short_option) {
1575 case 'f':
1576 m_force = true;
1577 break;
1578
1579 case 'D':
1580 m_use_dummy = true;
1581 break;
1582
1583 default:
1584 error.SetErrorStringWithFormat("unrecognized option '%c'",
1585 short_option);
1586 break;
1587 }
1588
1589 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001590 }
1591
Kate Stoneb9c1b512016-09-06 20:57:50 +00001592 void OptionParsingStarting(ExecutionContext *execution_context) override {
1593 m_use_dummy = false;
1594 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001595 }
1596
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001597 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001598 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001599 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001600
Kate Stoneb9c1b512016-09-06 20:57:50 +00001601 // Instance variables to hold the values for command options.
1602 bool m_use_dummy;
1603 bool m_force;
1604 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001605
Jim Ingham5a988412012-06-08 21:56:10 +00001606protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001607 bool DoExecute(Args &command, CommandReturnObject &result) override {
1608 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001609
Kate Stoneb9c1b512016-09-06 20:57:50 +00001610 if (target == nullptr) {
1611 result.AppendError("Invalid target. No existing target or breakpoints.");
1612 result.SetStatus(eReturnStatusFailed);
1613 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001614 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001615
Kate Stoneb9c1b512016-09-06 20:57:50 +00001616 std::unique_lock<std::recursive_mutex> lock;
1617 target->GetBreakpointList().GetListMutex(lock);
1618
1619 const BreakpointList &breakpoints = target->GetBreakpointList();
1620
1621 size_t num_breakpoints = breakpoints.GetSize();
1622
1623 if (num_breakpoints == 0) {
1624 result.AppendError("No breakpoints exist to be deleted.");
1625 result.SetStatus(eReturnStatusFailed);
1626 return false;
1627 }
1628
Zachary Turner11eb9c62016-10-05 20:03:37 +00001629 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001630 if (!m_options.m_force &&
1631 !m_interpreter.Confirm(
1632 "About to delete all breakpoints, do you want to do that?",
1633 true)) {
1634 result.AppendMessage("Operation cancelled...");
1635 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001636 target->RemoveAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001637 result.AppendMessageWithFormat(
1638 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1639 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1640 }
1641 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1642 } else {
1643 // Particular breakpoint selected; disable that breakpoint.
1644 BreakpointIDList valid_bp_ids;
1645 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001646 command, target, result, &valid_bp_ids,
1647 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001648
1649 if (result.Succeeded()) {
1650 int delete_count = 0;
1651 int disable_count = 0;
1652 const size_t count = valid_bp_ids.GetSize();
1653 for (size_t i = 0; i < count; ++i) {
1654 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1655
1656 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1657 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1658 Breakpoint *breakpoint =
1659 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1660 BreakpointLocation *location =
1661 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1662 // It makes no sense to try to delete individual locations, so we
1663 // disable them instead.
1664 if (location) {
1665 location->SetEnabled(false);
1666 ++disable_count;
1667 }
1668 } else {
1669 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1670 ++delete_count;
1671 }
1672 }
1673 }
1674 result.AppendMessageWithFormat(
1675 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1676 delete_count, disable_count);
1677 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1678 }
1679 }
1680 return result.Succeeded();
1681 }
1682
Jim Ingham33df7cd2014-12-06 01:28:03 +00001683private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001684 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001685};
1686
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001687//-------------------------------------------------------------------------
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001688// CommandObjectBreakpointName
1689//-------------------------------------------------------------------------
1690
Kate Stone7428a182016-07-14 22:03:10 +00001691static OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001692 // clang-format off
Jim Inghame9632eb2017-09-15 00:52:35 +00001693 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1694 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
Jim Inghamb842f2e2017-09-14 20:22:49 +00001695 {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
Jim Inghame9632eb2017-09-15 00:52:35 +00001696 {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeNone, "A help string describing the purpose of this name."},
Kate Stoneb9c1b512016-09-06 20:57:50 +00001697 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001698};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001699class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001700public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001701 BreakpointNameOptionGroup()
1702 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1703 }
1704
1705 ~BreakpointNameOptionGroup() override = default;
1706
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001707 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001708 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001709 }
1710
Zachary Turner97206d52017-05-12 04:51:55 +00001711 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1712 ExecutionContext *execution_context) override {
1713 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001714 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1715
1716 switch (short_option) {
1717 case 'N':
Zachary Turnerfe114832016-11-12 16:56:47 +00001718 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001719 error.Success())
Zachary Turnerfe114832016-11-12 16:56:47 +00001720 m_name.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001721 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001722 case 'B':
Zachary Turnerfe114832016-11-12 16:56:47 +00001723 if (m_breakpoint.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001724 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001725 "unrecognized value \"%s\" for breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +00001726 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001727 break;
1728 case 'D':
Zachary Turnerfe114832016-11-12 16:56:47 +00001729 if (m_use_dummy.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001730 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001731 "unrecognized value \"%s\" for use-dummy",
Zachary Turnerfe114832016-11-12 16:56:47 +00001732 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001733 break;
Jim Inghame9632eb2017-09-15 00:52:35 +00001734 case 'H':
1735 m_help_string.SetValueFromString(option_arg);
1736 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001737
1738 default:
1739 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1740 short_option);
1741 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001742 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001743 return error;
1744 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001745
Kate Stoneb9c1b512016-09-06 20:57:50 +00001746 void OptionParsingStarting(ExecutionContext *execution_context) override {
1747 m_name.Clear();
1748 m_breakpoint.Clear();
1749 m_use_dummy.Clear();
1750 m_use_dummy.SetDefaultValue(false);
Jim Inghame9632eb2017-09-15 00:52:35 +00001751 m_help_string.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001752 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001753
Kate Stoneb9c1b512016-09-06 20:57:50 +00001754 OptionValueString m_name;
1755 OptionValueUInt64 m_breakpoint;
1756 OptionValueBoolean m_use_dummy;
Jim Inghame9632eb2017-09-15 00:52:35 +00001757 OptionValueString m_help_string;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001758};
1759
Jim Inghamb842f2e2017-09-14 20:22:49 +00001760static OptionDefinition g_breakpoint_access_options[] = {
1761 // clang-format off
1762 {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."},
1763 {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."},
1764 {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."},
1765 // clang-format on
1766};
1767
1768class BreakpointAccessOptionGroup : public OptionGroup
1769{
1770public:
1771 BreakpointAccessOptionGroup() :
1772 OptionGroup()
1773 {}
1774
1775 ~BreakpointAccessOptionGroup() override = default;
1776
1777 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1778 return llvm::makeArrayRef(g_breakpoint_access_options);
1779 }
1780 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1781 ExecutionContext *execution_context) override {
1782 Status error;
1783 const int short_option
1784 = g_breakpoint_access_options[option_idx].short_option;
1785
1786 switch (short_option) {
1787 case 'L': {
1788 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001789 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001790 if (success) {
1791 m_permissions.SetAllowList(value);
1792 } else
1793 error.SetErrorStringWithFormat(
1794 "invalid boolean value '%s' passed for -L option",
1795 option_arg.str().c_str());
1796 } break;
1797 case 'A': {
1798 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001799 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001800 if (success) {
1801 m_permissions.SetAllowDisable(value);
1802 } else
1803 error.SetErrorStringWithFormat(
1804 "invalid boolean value '%s' passed for -L option",
1805 option_arg.str().c_str());
1806 } break;
1807 case 'D': {
1808 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001809 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001810 if (success) {
1811 m_permissions.SetAllowDelete(value);
1812 } else
1813 error.SetErrorStringWithFormat(
1814 "invalid boolean value '%s' passed for -L option",
1815 option_arg.str().c_str());
1816 } break;
1817
1818 }
1819
1820 return error;
1821 }
1822
1823 void OptionParsingStarting(ExecutionContext *execution_context) override {
1824 }
1825
1826 const BreakpointName::Permissions &GetPermissions() const
1827 {
1828 return m_permissions;
1829 }
1830 BreakpointName::Permissions m_permissions;
1831};
1832
1833class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1834public:
1835 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1836 : CommandObjectParsed(
1837 interpreter, "configure", "Configure the options for the breakpoint"
1838 " name provided. "
1839 "If you provide a breakpoint id, the options will be copied from "
1840 "the breakpoint, otherwise only the options specified will be set "
1841 "on the name.",
1842 "breakpoint name configure <command-options> "
1843 "<breakpoint-name-list>"),
1844 m_bp_opts(), m_option_group() {
1845 // Create the first variant for the first (and only) argument for this
1846 // command.
1847 CommandArgumentEntry arg1;
1848 CommandArgumentData id_arg;
1849 id_arg.arg_type = eArgTypeBreakpointName;
1850 id_arg.arg_repetition = eArgRepeatOptional;
1851 arg1.push_back(id_arg);
1852 m_arguments.push_back(arg1);
1853
1854 m_option_group.Append(&m_bp_opts,
1855 LLDB_OPT_SET_ALL,
1856 LLDB_OPT_SET_1);
1857 m_option_group.Append(&m_access_options,
1858 LLDB_OPT_SET_ALL,
1859 LLDB_OPT_SET_ALL);
Jim Inghame9632eb2017-09-15 00:52:35 +00001860 m_option_group.Append(&m_bp_id,
1861 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1862 LLDB_OPT_SET_ALL);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001863 m_option_group.Finalize();
1864 }
1865
1866 ~CommandObjectBreakpointNameConfigure() override = default;
1867
1868 Options *GetOptions() override { return &m_option_group; }
1869
1870protected:
1871 bool DoExecute(Args &command, CommandReturnObject &result) override {
1872
1873 const size_t argc = command.GetArgumentCount();
1874 if (argc == 0) {
1875 result.AppendError("No names provided.");
1876 result.SetStatus(eReturnStatusFailed);
1877 return false;
1878 }
1879
1880 Target *target =
1881 GetSelectedOrDummyTarget(false);
1882
1883 if (target == nullptr) {
1884 result.AppendError("Invalid target. No existing target or breakpoints.");
1885 result.SetStatus(eReturnStatusFailed);
1886 return false;
1887 }
1888
1889 std::unique_lock<std::recursive_mutex> lock;
1890 target->GetBreakpointList().GetListMutex(lock);
1891
1892 // Make a pass through first to see that all the names are legal.
1893 for (auto &entry : command.entries()) {
1894 Status error;
1895 if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1896 {
1897 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1898 entry.c_str(), error.AsCString());
1899 result.SetStatus(eReturnStatusFailed);
1900 return false;
1901 }
1902 }
Adrian Prantl05097242018-04-30 16:49:04 +00001903 // Now configure them, we already pre-checked the names so we don't need to
1904 // check the error:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001905 BreakpointSP bp_sp;
1906 if (m_bp_id.m_breakpoint.OptionWasSet())
1907 {
1908 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1909 bp_sp = target->GetBreakpointByID(bp_id);
1910 if (!bp_sp)
1911 {
1912 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1913 bp_id);
1914 result.SetStatus(eReturnStatusFailed);
1915 return false;
1916 }
1917 }
1918
1919 Status error;
1920 for (auto &entry : command.entries()) {
1921 ConstString name(entry.c_str());
1922 BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1923 if (!bp_name)
1924 continue;
Jim Inghame9632eb2017-09-15 00:52:35 +00001925 if (m_bp_id.m_help_string.OptionWasSet())
1926 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1927
Jim Inghamb842f2e2017-09-14 20:22:49 +00001928 if (bp_sp)
1929 target->ConfigureBreakpointName(*bp_name,
1930 *bp_sp->GetOptions(),
1931 m_access_options.GetPermissions());
1932 else
1933 target->ConfigureBreakpointName(*bp_name,
1934 m_bp_opts.GetBreakpointOptions(),
1935 m_access_options.GetPermissions());
1936 }
1937 return true;
1938 }
1939
1940private:
1941 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1942 BreakpointOptionGroup m_bp_opts;
1943 BreakpointAccessOptionGroup m_access_options;
1944 OptionGroupOptions m_option_group;
1945};
1946
Kate Stoneb9c1b512016-09-06 20:57:50 +00001947class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001948public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001949 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1950 : CommandObjectParsed(
1951 interpreter, "add", "Add a name to the breakpoints provided.",
1952 "breakpoint name add <command-options> <breakpoint-id-list>"),
1953 m_name_options(), m_option_group() {
1954 // Create the first variant for the first (and only) argument for this
1955 // command.
1956 CommandArgumentEntry arg1;
1957 CommandArgumentData id_arg;
1958 id_arg.arg_type = eArgTypeBreakpointID;
1959 id_arg.arg_repetition = eArgRepeatOptional;
1960 arg1.push_back(id_arg);
1961 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001962
Kate Stoneb9c1b512016-09-06 20:57:50 +00001963 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1964 m_option_group.Finalize();
1965 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001966
Kate Stoneb9c1b512016-09-06 20:57:50 +00001967 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001968
Kate Stoneb9c1b512016-09-06 20:57:50 +00001969 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001970
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001971protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001972 bool DoExecute(Args &command, CommandReturnObject &result) override {
1973 if (!m_name_options.m_name.OptionWasSet()) {
1974 result.SetError("No name option provided.");
1975 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001976 }
1977
Kate Stoneb9c1b512016-09-06 20:57:50 +00001978 Target *target =
1979 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1980
1981 if (target == nullptr) {
1982 result.AppendError("Invalid target. No existing target or breakpoints.");
1983 result.SetStatus(eReturnStatusFailed);
1984 return false;
1985 }
1986
1987 std::unique_lock<std::recursive_mutex> lock;
1988 target->GetBreakpointList().GetListMutex(lock);
1989
1990 const BreakpointList &breakpoints = target->GetBreakpointList();
1991
1992 size_t num_breakpoints = breakpoints.GetSize();
1993 if (num_breakpoints == 0) {
1994 result.SetError("No breakpoints, cannot add names.");
1995 result.SetStatus(eReturnStatusFailed);
1996 return false;
1997 }
1998
1999 // Particular breakpoint selected; disable that breakpoint.
2000 BreakpointIDList valid_bp_ids;
2001 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002002 command, target, result, &valid_bp_ids,
2003 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002004
2005 if (result.Succeeded()) {
2006 if (valid_bp_ids.GetSize() == 0) {
2007 result.SetError("No breakpoints specified, cannot add names.");
2008 result.SetStatus(eReturnStatusFailed);
2009 return false;
2010 }
2011 size_t num_valid_ids = valid_bp_ids.GetSize();
Jim Inghamb842f2e2017-09-14 20:22:49 +00002012 const char *bp_name = m_name_options.m_name.GetCurrentValue();
2013 Status error; // This error reports illegal names, but we've already
2014 // checked that, so we don't need to check it again here.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002015 for (size_t index = 0; index < num_valid_ids; index++) {
2016 lldb::break_id_t bp_id =
2017 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2018 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002019 target->AddNameToBreakpoint(bp_sp, bp_name, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002020 }
2021 }
2022
2023 return true;
2024 }
2025
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002026private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002027 BreakpointNameOptionGroup m_name_options;
2028 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002029};
2030
Kate Stoneb9c1b512016-09-06 20:57:50 +00002031class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002032public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002033 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
2034 : CommandObjectParsed(
2035 interpreter, "delete",
2036 "Delete a name from the breakpoints provided.",
2037 "breakpoint name delete <command-options> <breakpoint-id-list>"),
2038 m_name_options(), m_option_group() {
2039 // Create the first variant for the first (and only) argument for this
2040 // command.
2041 CommandArgumentEntry arg1;
2042 CommandArgumentData id_arg;
2043 id_arg.arg_type = eArgTypeBreakpointID;
2044 id_arg.arg_repetition = eArgRepeatOptional;
2045 arg1.push_back(id_arg);
2046 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002047
Kate Stoneb9c1b512016-09-06 20:57:50 +00002048 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
2049 m_option_group.Finalize();
2050 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002051
Kate Stoneb9c1b512016-09-06 20:57:50 +00002052 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002053
Kate Stoneb9c1b512016-09-06 20:57:50 +00002054 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002055
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002056protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002057 bool DoExecute(Args &command, CommandReturnObject &result) override {
2058 if (!m_name_options.m_name.OptionWasSet()) {
2059 result.SetError("No name option provided.");
2060 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002061 }
2062
Kate Stoneb9c1b512016-09-06 20:57:50 +00002063 Target *target =
2064 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
2065
2066 if (target == nullptr) {
2067 result.AppendError("Invalid target. No existing target or breakpoints.");
2068 result.SetStatus(eReturnStatusFailed);
2069 return false;
2070 }
2071
2072 std::unique_lock<std::recursive_mutex> lock;
2073 target->GetBreakpointList().GetListMutex(lock);
2074
2075 const BreakpointList &breakpoints = target->GetBreakpointList();
2076
2077 size_t num_breakpoints = breakpoints.GetSize();
2078 if (num_breakpoints == 0) {
2079 result.SetError("No breakpoints, cannot delete names.");
2080 result.SetStatus(eReturnStatusFailed);
2081 return false;
2082 }
2083
2084 // Particular breakpoint selected; disable that breakpoint.
2085 BreakpointIDList valid_bp_ids;
2086 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002087 command, target, result, &valid_bp_ids,
2088 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002089
2090 if (result.Succeeded()) {
2091 if (valid_bp_ids.GetSize() == 0) {
2092 result.SetError("No breakpoints specified, cannot delete names.");
2093 result.SetStatus(eReturnStatusFailed);
2094 return false;
2095 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002096 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
Kate Stoneb9c1b512016-09-06 20:57:50 +00002097 size_t num_valid_ids = valid_bp_ids.GetSize();
2098 for (size_t index = 0; index < num_valid_ids; index++) {
2099 lldb::break_id_t bp_id =
2100 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2101 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002102 target->RemoveNameFromBreakpoint(bp_sp, bp_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002103 }
2104 }
2105
2106 return true;
2107 }
2108
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002109private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002110 BreakpointNameOptionGroup m_name_options;
2111 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002112};
2113
Kate Stoneb9c1b512016-09-06 20:57:50 +00002114class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002115public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002116 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2117 : CommandObjectParsed(interpreter, "list",
Jim Inghamb842f2e2017-09-14 20:22:49 +00002118 "List either the names for a breakpoint or info "
2119 "about a given name. With no arguments, lists all "
2120 "names",
Kate Stoneb9c1b512016-09-06 20:57:50 +00002121 "breakpoint name list <command-options>"),
2122 m_name_options(), m_option_group() {
Jim Inghamb842f2e2017-09-14 20:22:49 +00002123 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002124 m_option_group.Finalize();
2125 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002126
Kate Stoneb9c1b512016-09-06 20:57:50 +00002127 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002128
Kate Stoneb9c1b512016-09-06 20:57:50 +00002129 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002130
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002131protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002132 bool DoExecute(Args &command, CommandReturnObject &result) override {
2133 Target *target =
2134 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002135
Kate Stoneb9c1b512016-09-06 20:57:50 +00002136 if (target == nullptr) {
2137 result.AppendError("Invalid target. No existing target or breakpoints.");
2138 result.SetStatus(eReturnStatusFailed);
2139 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002140 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002141
2142
2143 std::vector<std::string> name_list;
2144 if (command.empty()) {
2145 target->GetBreakpointNames(name_list);
2146 } else {
2147 for (const Args::ArgEntry &arg : command)
2148 {
2149 name_list.push_back(arg.c_str());
2150 }
2151 }
2152
2153 if (name_list.empty()) {
2154 result.AppendMessage("No breakpoint names found.");
2155 } else {
2156 for (const std::string &name_str : name_list) {
2157 const char *name = name_str.c_str();
2158 // First print out the options for the name:
2159 Status error;
2160 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2161 false,
2162 error);
2163 if (bp_name)
2164 {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002165 StreamString s;
Jim Inghamb842f2e2017-09-14 20:22:49 +00002166 result.AppendMessageWithFormat("Name: %s\n", name);
2167 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2168 {
2169 result.AppendMessage(s.GetString());
2170 }
2171
2172 std::unique_lock<std::recursive_mutex> lock;
2173 target->GetBreakpointList().GetListMutex(lock);
2174
2175 BreakpointList &breakpoints = target->GetBreakpointList();
2176 bool any_set = false;
2177 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2178 if (bp_sp->MatchesName(name)) {
2179 StreamString s;
2180 any_set = true;
2181 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2182 s.EOL();
2183 result.AppendMessage(s.GetString());
2184 }
2185 }
2186 if (!any_set)
2187 result.AppendMessage("No breakpoints using this name.");
2188 } else {
2189 result.AppendMessageWithFormat("Name: %s not found.\n", name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002190 }
2191 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002192 }
2193 return true;
2194 }
2195
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002196private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002197 BreakpointNameOptionGroup m_name_options;
2198 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002199};
2200
2201//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002202// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002203//-------------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00002204class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002205public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002206 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2207 : CommandObjectMultiword(
2208 interpreter, "name", "Commands to manage name tags for breakpoints",
2209 "breakpoint name <subcommand> [<command-options>]") {
2210 CommandObjectSP add_command_object(
2211 new CommandObjectBreakpointNameAdd(interpreter));
2212 CommandObjectSP delete_command_object(
2213 new CommandObjectBreakpointNameDelete(interpreter));
2214 CommandObjectSP list_command_object(
2215 new CommandObjectBreakpointNameList(interpreter));
Jim Inghamb842f2e2017-09-14 20:22:49 +00002216 CommandObjectSP configure_command_object(
2217 new CommandObjectBreakpointNameConfigure(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002218
Kate Stoneb9c1b512016-09-06 20:57:50 +00002219 LoadSubCommand("add", add_command_object);
2220 LoadSubCommand("delete", delete_command_object);
2221 LoadSubCommand("list", list_command_object);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002222 LoadSubCommand("configure", configure_command_object);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002223 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002224
Kate Stoneb9c1b512016-09-06 20:57:50 +00002225 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002226};
2227
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002228//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002229// CommandObjectBreakpointRead
2230//-------------------------------------------------------------------------
Jim Ingham3acdf382016-09-22 22:20:28 +00002231#pragma mark Read::CommandOptions
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002232static OptionDefinition g_breakpoint_read_options[] = {
2233 // clang-format off
Jim Ingham3acdf382016-09-22 22:20:28 +00002234 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2235 {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."},
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002236 // clang-format on
2237};
2238
2239#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002240
2241class CommandObjectBreakpointRead : public CommandObjectParsed {
2242public:
2243 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2244 : CommandObjectParsed(interpreter, "breakpoint read",
2245 "Read and set the breakpoints previously saved to "
2246 "a file with \"breakpoint write\". ",
2247 nullptr),
2248 m_options() {
2249 CommandArgumentEntry arg;
2250 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2251 eArgTypeBreakpointIDRange);
2252 // Add the entry for the first argument for this command to the object's
2253 // arguments vector.
2254 m_arguments.push_back(arg);
2255 }
2256
2257 ~CommandObjectBreakpointRead() override = default;
2258
2259 Options *GetOptions() override { return &m_options; }
2260
2261 class CommandOptions : public Options {
2262 public:
2263 CommandOptions() : Options() {}
2264
2265 ~CommandOptions() override = default;
2266
Zachary Turner97206d52017-05-12 04:51:55 +00002267 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2268 ExecutionContext *execution_context) override {
2269 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002270 const int short_option = m_getopt_table[option_idx].val;
2271
2272 switch (short_option) {
2273 case 'f':
2274 m_filename.assign(option_arg);
2275 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002276 case 'N': {
Zachary Turner97206d52017-05-12 04:51:55 +00002277 Status name_error;
Jim Ingham3acdf382016-09-22 22:20:28 +00002278 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2279 name_error)) {
2280 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2281 name_error.AsCString());
2282 }
2283 m_names.push_back(option_arg);
2284 break;
2285 }
Jim Inghame14dc262016-09-12 23:10:56 +00002286 default:
2287 error.SetErrorStringWithFormat("unrecognized option '%c'",
2288 short_option);
2289 break;
2290 }
2291
2292 return error;
2293 }
2294
2295 void OptionParsingStarting(ExecutionContext *execution_context) override {
2296 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002297 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002298 }
2299
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002300 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002301 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002302 }
Jim Inghame14dc262016-09-12 23:10:56 +00002303
2304 // Instance variables to hold the values for command options.
2305
2306 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002307 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002308 };
2309
2310protected:
2311 bool DoExecute(Args &command, CommandReturnObject &result) override {
2312 Target *target = GetSelectedOrDummyTarget();
2313 if (target == nullptr) {
2314 result.AppendError("Invalid target. No existing target or breakpoints.");
2315 result.SetStatus(eReturnStatusFailed);
2316 return false;
2317 }
2318
Jim Ingham3acdf382016-09-22 22:20:28 +00002319 std::unique_lock<std::recursive_mutex> lock;
2320 target->GetBreakpointList().GetListMutex(lock);
2321
Jim Inghame14dc262016-09-12 23:10:56 +00002322 FileSpec input_spec(m_options.m_filename, true);
Jim Ingham01f16662016-09-14 19:07:35 +00002323 BreakpointIDList new_bps;
Zachary Turner97206d52017-05-12 04:51:55 +00002324 Status error = target->CreateBreakpointsFromFile(
2325 input_spec, m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002326
Jim Inghame14dc262016-09-12 23:10:56 +00002327 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002328 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002329 result.SetStatus(eReturnStatusFailed);
2330 return false;
2331 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002332
2333 Stream &output_stream = result.GetOutputStream();
2334
2335 size_t num_breakpoints = new_bps.GetSize();
2336 if (num_breakpoints == 0) {
2337 result.AppendMessage("No breakpoints added.");
2338 } else {
2339 // No breakpoint selected; show info about all currently set breakpoints.
2340 result.AppendMessage("New breakpoints:");
2341 for (size_t i = 0; i < num_breakpoints; ++i) {
2342 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2343 Breakpoint *bp = target->GetBreakpointList()
2344 .FindBreakpointByID(bp_id.GetBreakpointID())
2345 .get();
2346 if (bp)
2347 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2348 false);
2349 }
2350 }
Jim Inghame14dc262016-09-12 23:10:56 +00002351 return result.Succeeded();
2352 }
2353
2354private:
2355 CommandOptions m_options;
2356};
2357
Jim Inghame14dc262016-09-12 23:10:56 +00002358//-------------------------------------------------------------------------
2359// CommandObjectBreakpointWrite
2360//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002361#pragma mark Write::CommandOptions
2362static OptionDefinition g_breakpoint_write_options[] = {
2363 // clang-format off
Jim Ingham2d3628e2016-09-22 23:42:42 +00002364 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2365 { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."},
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002366 // clang-format on
2367};
2368
2369#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002370class CommandObjectBreakpointWrite : public CommandObjectParsed {
2371public:
2372 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2373 : CommandObjectParsed(interpreter, "breakpoint write",
2374 "Write the breakpoints listed to a file that can "
2375 "be read in with \"breakpoint read\". "
2376 "If given no arguments, writes all breakpoints.",
2377 nullptr),
2378 m_options() {
2379 CommandArgumentEntry arg;
2380 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2381 eArgTypeBreakpointIDRange);
2382 // Add the entry for the first argument for this command to the object's
2383 // arguments vector.
2384 m_arguments.push_back(arg);
2385 }
2386
2387 ~CommandObjectBreakpointWrite() override = default;
2388
2389 Options *GetOptions() override { return &m_options; }
2390
2391 class CommandOptions : public Options {
2392 public:
2393 CommandOptions() : Options() {}
2394
2395 ~CommandOptions() override = default;
2396
Zachary Turner97206d52017-05-12 04:51:55 +00002397 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2398 ExecutionContext *execution_context) override {
2399 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002400 const int short_option = m_getopt_table[option_idx].val;
2401
2402 switch (short_option) {
2403 case 'f':
2404 m_filename.assign(option_arg);
2405 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002406 case 'a':
2407 m_append = true;
2408 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002409 default:
2410 error.SetErrorStringWithFormat("unrecognized option '%c'",
2411 short_option);
2412 break;
2413 }
2414
2415 return error;
2416 }
2417
2418 void OptionParsingStarting(ExecutionContext *execution_context) override {
2419 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002420 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002421 }
2422
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002423 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002424 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002425 }
Jim Inghame14dc262016-09-12 23:10:56 +00002426
2427 // Instance variables to hold the values for command options.
2428
2429 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002430 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002431 };
2432
2433protected:
2434 bool DoExecute(Args &command, CommandReturnObject &result) override {
2435 Target *target = GetSelectedOrDummyTarget();
2436 if (target == nullptr) {
2437 result.AppendError("Invalid target. No existing target or breakpoints.");
2438 result.SetStatus(eReturnStatusFailed);
2439 return false;
2440 }
2441
Jim Inghame14dc262016-09-12 23:10:56 +00002442 std::unique_lock<std::recursive_mutex> lock;
2443 target->GetBreakpointList().GetListMutex(lock);
2444
Jim Ingham01f16662016-09-14 19:07:35 +00002445 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002446 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002447 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002448 command, target, result, &valid_bp_ids,
2449 BreakpointName::Permissions::PermissionKinds::listPerm);
Jim Inghame14dc262016-09-12 23:10:56 +00002450
Jim Ingham01f16662016-09-14 19:07:35 +00002451 if (!result.Succeeded()) {
2452 result.SetStatus(eReturnStatusFailed);
2453 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002454 }
2455 }
Zachary Turner97206d52017-05-12 04:51:55 +00002456 Status error = target->SerializeBreakpointsToFile(
Malcolm Parsons771ef6d2016-11-02 20:34:10 +00002457 FileSpec(m_options.m_filename, true), valid_bp_ids, m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002458 if (!error.Success()) {
2459 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2460 error.AsCString());
2461 result.SetStatus(eReturnStatusFailed);
2462 }
Jim Inghame14dc262016-09-12 23:10:56 +00002463 return result.Succeeded();
2464 }
2465
2466private:
2467 CommandOptions m_options;
2468};
2469
Jim Inghame14dc262016-09-12 23:10:56 +00002470//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002471// CommandObjectMultiwordBreakpoint
2472//-------------------------------------------------------------------------
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002473#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002474
Kate Stoneb9c1b512016-09-06 20:57:50 +00002475CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2476 CommandInterpreter &interpreter)
2477 : CommandObjectMultiword(
2478 interpreter, "breakpoint",
2479 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2480 "breakpoint <subcommand> [<command-options>]") {
2481 CommandObjectSP list_command_object(
2482 new CommandObjectBreakpointList(interpreter));
2483 CommandObjectSP enable_command_object(
2484 new CommandObjectBreakpointEnable(interpreter));
2485 CommandObjectSP disable_command_object(
2486 new CommandObjectBreakpointDisable(interpreter));
2487 CommandObjectSP clear_command_object(
2488 new CommandObjectBreakpointClear(interpreter));
2489 CommandObjectSP delete_command_object(
2490 new CommandObjectBreakpointDelete(interpreter));
2491 CommandObjectSP set_command_object(
2492 new CommandObjectBreakpointSet(interpreter));
2493 CommandObjectSP command_command_object(
2494 new CommandObjectBreakpointCommand(interpreter));
2495 CommandObjectSP modify_command_object(
2496 new CommandObjectBreakpointModify(interpreter));
2497 CommandObjectSP name_command_object(
2498 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002499 CommandObjectSP write_command_object(
2500 new CommandObjectBreakpointWrite(interpreter));
2501 CommandObjectSP read_command_object(
2502 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002503
Kate Stoneb9c1b512016-09-06 20:57:50 +00002504 list_command_object->SetCommandName("breakpoint list");
2505 enable_command_object->SetCommandName("breakpoint enable");
2506 disable_command_object->SetCommandName("breakpoint disable");
2507 clear_command_object->SetCommandName("breakpoint clear");
2508 delete_command_object->SetCommandName("breakpoint delete");
2509 set_command_object->SetCommandName("breakpoint set");
2510 command_command_object->SetCommandName("breakpoint command");
2511 modify_command_object->SetCommandName("breakpoint modify");
2512 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002513 write_command_object->SetCommandName("breakpoint write");
2514 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002515
Kate Stoneb9c1b512016-09-06 20:57:50 +00002516 LoadSubCommand("list", list_command_object);
2517 LoadSubCommand("enable", enable_command_object);
2518 LoadSubCommand("disable", disable_command_object);
2519 LoadSubCommand("clear", clear_command_object);
2520 LoadSubCommand("delete", delete_command_object);
2521 LoadSubCommand("set", set_command_object);
2522 LoadSubCommand("command", command_command_object);
2523 LoadSubCommand("modify", modify_command_object);
2524 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002525 LoadSubCommand("write", write_command_object);
2526 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002527}
2528
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002529CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002530
Kate Stoneb9c1b512016-09-06 20:57:50 +00002531void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2532 bool allow_locations,
2533 CommandReturnObject &result,
Jim Inghamb842f2e2017-09-14 20:22:49 +00002534 BreakpointIDList *valid_ids,
2535 BreakpointName::Permissions
2536 ::PermissionKinds
2537 purpose) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002538 // args can be strings representing 1). integers (for breakpoint ids)
2539 // 2). the full breakpoint & location
2540 // canonical representation
2541 // 3). the word "to" or a hyphen,
2542 // representing a range (in which case there
2543 // had *better* be an entry both before &
2544 // after of one of the first two types.
2545 // 4). A breakpoint name
2546 // If args is empty, we will use the last created breakpoint (if there is
2547 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002548
Kate Stoneb9c1b512016-09-06 20:57:50 +00002549 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002550
Zachary Turner11eb9c62016-10-05 20:03:37 +00002551 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002552 if (target->GetLastCreatedBreakpoint()) {
2553 valid_ids->AddBreakpointID(BreakpointID(
2554 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2555 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2556 } else {
2557 result.AppendError(
2558 "No breakpoint specified and no last created breakpoint.");
2559 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002560 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002561 return;
2562 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002563
Kate Stoneb9c1b512016-09-06 20:57:50 +00002564 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
Adrian Prantl05097242018-04-30 16:49:04 +00002565 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2566 // id range strings over; instead generate a list of strings for all the
2567 // breakpoint ids in the range, and shove all of those breakpoint id strings
2568 // into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002569
Jim Inghamb842f2e2017-09-14 20:22:49 +00002570 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2571 purpose, result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002572
Kate Stoneb9c1b512016-09-06 20:57:50 +00002573 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2574 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002575
Pavel Labath16662f32018-06-20 08:12:50 +00002576 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002577
Adrian Prantl05097242018-04-30 16:49:04 +00002578 // At this point, all of the breakpoint ids that the user passed in have
2579 // been converted to breakpoint IDs and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002580
Kate Stoneb9c1b512016-09-06 20:57:50 +00002581 if (result.Succeeded()) {
2582 // Now that we've converted everything from args into a list of breakpoint
Adrian Prantl05097242018-04-30 16:49:04 +00002583 // ids, go through our tentative list of breakpoint id's and verify that
2584 // they correspond to valid/currently set breakpoints.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002585
2586 const size_t count = valid_ids->GetSize();
2587 for (size_t i = 0; i < count; ++i) {
2588 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2589 Breakpoint *breakpoint =
2590 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2591 if (breakpoint != nullptr) {
2592 const size_t num_locations = breakpoint->GetNumLocations();
2593 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2594 StreamString id_str;
2595 BreakpointID::GetCanonicalReference(
2596 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2597 i = valid_ids->GetSize() + 1;
2598 result.AppendErrorWithFormat(
2599 "'%s' is not a currently valid breakpoint/location id.\n",
2600 id_str.GetData());
2601 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002602 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002603 } else {
2604 i = valid_ids->GetSize() + 1;
2605 result.AppendErrorWithFormat(
2606 "'%d' is not a currently valid breakpoint ID.\n",
2607 cur_bp_id.GetBreakpointID());
2608 result.SetStatus(eReturnStatusFailed);
2609 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002610 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002611 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002612}