blob: dcf6fa24c1a4fc9c50615d2ee91f0ddf4b90967a [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"
Kate Stoneb9c1b512016-09-06 20:57:50 +000021#include "lldb/Core/RegularExpression.h"
22#include "lldb/Core/StreamString.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000023#include "lldb/Host/StringConvert.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000024#include "lldb/Interpreter/CommandCompletions.h"
25#include "lldb/Interpreter/CommandInterpreter.h"
26#include "lldb/Interpreter/CommandReturnObject.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000027#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000028#include "lldb/Interpreter/OptionValueString.h"
29#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000030#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000031#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000032#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000033#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000034#include "lldb/Target/Thread.h"
35#include "lldb/Target/ThreadSpec.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036
37using namespace lldb;
38using namespace lldb_private;
39
Kate Stoneb9c1b512016-09-06 20:57:50 +000040static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
41 lldb::DescriptionLevel level) {
42 s->IndentMore();
43 bp->GetDescription(s, level, true);
44 s->IndentLess();
45 s->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046}
47
Zachary Turner1f0f5b52016-09-22 20:22:55 +000048// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to
49// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately.
50#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2)
51#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10)
52#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
53#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8))
54#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9)
55#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8))
56
57static OptionDefinition g_breakpoint_set_options[] = {
58 // clang-format off
59 { 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 "
60 "multiple times to specify multiple shared libraries." },
61 { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
62 { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "The breakpoint is deleted the first time it causes a stop." },
63 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
64 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose indeX matches this argument." },
65 { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
66 { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this "
67 "argument." },
68 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." },
69 { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by "
70 "this argument." },
71 { 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 "
72 "lldb only looks for files that are #included if they use the standard include "
73 "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are "
74 "#included, set target.inline-breakpoint-strategy to \"always\"." },
75 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." },
76
77 // Comment out this option for the moment, as we don't actually use it, but will in the future.
78 // This way users won't see it, but the infrastructure is left in place.
79 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>",
80 // "Set the breakpoint by source location at this particular column."},
81
82 { 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 "
83 "a particular binary, then the address will be converted to a \"file\" "
84 "address, so that the breakpoint will track that binary+offset no matter where "
85 "the binary eventually loads. Alternately, if you also specify the module - "
86 "with the -s option - then the address will be treated as a file address in "
87 "that module, and resolved accordingly. Again, this will allow lldb to track "
88 "that offset on subsequent reloads. The module need not have been loaded at "
89 "the time you specify this breakpoint, and will get resolved when the module "
90 "is loaded." },
91 { 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 "
92 "one breakpoint for multiple names" },
93 { 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 "
94 "functions. Can be repeated multiple times." },
95 { 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 "
96 "namespaces and all arguments, and for Objective C this means a full function "
97 "prototype with class and selector. Can be repeated multiple times to make "
98 "one breakpoint for multiple names." },
99 { 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 "
100 "make one breakpoint for multiple Selectors." },
101 { 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 "
102 "make one breakpoint for multiple methods." },
103 { 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 "
104 "the function name(s)." },
105 { 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 "
106 "ignored). Can be repeated multiple times to make one breakpoint for multiple "
107 "symbols." },
108 { 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 "
109 "against the source text in a source file or files specified with the -f "
110 "option. The -f option can be specified more than once. If no source files "
111 "are specified, uses the current \"default source file\". If you want to "
112 "match against all source files, pass the \"--all-files\" option." },
113 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "All files are searched for source pattern matches." },
114 { 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 "
115 "options, on throw but not catch.)" },
116 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." },
117 { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." },
118
119 // Don't add this option till it actually does something useful...
120 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName,
121 // "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" },
122
123 { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression "
124 "(note: currently only implemented for setting breakpoints on identifiers). "
125 "If not set the target.language setting is used." },
126 { 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. "
127 "If not set the target.skip-prologue setting is used." },
128 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, "
129 "which prime new targets." },
130 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." },
131 { 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. "
132 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." },
133 { 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 "
134 "setting is used." },
135 // clang-format on
136};
137
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000138//-------------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000139// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000140//-------------------------------------------------------------------------
141
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000143public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 typedef enum BreakpointSetType {
145 eSetTypeInvalid,
146 eSetTypeFileAndLine,
147 eSetTypeAddress,
148 eSetTypeFunctionName,
149 eSetTypeFunctionRegexp,
150 eSetTypeSourceRegexp,
151 eSetTypeException
152 } BreakpointSetType;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
155 : CommandObjectParsed(
156 interpreter, "breakpoint set",
157 "Sets a breakpoint or set of breakpoints in the executable.",
158 "breakpoint set <cmd-options>"),
159 m_options() {}
160
161 ~CommandObjectBreakpointSet() override = default;
162
163 Options *GetOptions() override { return &m_options; }
164
165 class CommandOptions : public Options {
166 public:
167 CommandOptions()
168 : Options(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
169 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
170 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
171 m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
172 m_thread_index(UINT32_MAX), m_thread_name(), m_queue_name(),
173 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
174 m_exception_language(eLanguageTypeUnknown),
175 m_language(lldb::eLanguageTypeUnknown),
176 m_skip_prologue(eLazyBoolCalculate), m_one_shot(false),
177 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
178
179 ~CommandOptions() override = default;
180
181 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
182 ExecutionContext *execution_context) override {
183 Error error;
184 const int short_option = m_getopt_table[option_idx].val;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000185 llvm::StringRef option_strref(option_arg ? option_arg : "");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000186
187 switch (short_option) {
188 case 'a': {
189 m_load_addr = Args::StringToAddress(execution_context, option_arg,
190 LLDB_INVALID_ADDRESS, &error);
191 } break;
192
193 case 'A':
194 m_all_files = true;
195 break;
196
197 case 'b':
198 m_func_names.push_back(option_arg);
199 m_func_name_type_mask |= eFunctionNameTypeBase;
200 break;
201
202 case 'C': {
203 bool success;
204 m_column = StringConvert::ToUInt32(option_arg, 0, 0, &success);
205 if (!success)
206 error.SetErrorStringWithFormat("invalid column number: %s",
207 option_arg);
208 break;
209 }
210
211 case 'c':
212 m_condition.assign(option_arg);
213 break;
214
215 case 'D':
216 m_use_dummy = true;
217 break;
218
219 case 'E': {
Zachary Turner8cef4b02016-09-23 17:48:13 +0000220 LanguageType language =
221 Language::GetLanguageTypeFromString(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000222
223 switch (language) {
224 case eLanguageTypeC89:
225 case eLanguageTypeC:
226 case eLanguageTypeC99:
227 case eLanguageTypeC11:
228 m_exception_language = eLanguageTypeC;
229 break;
230 case eLanguageTypeC_plus_plus:
231 case eLanguageTypeC_plus_plus_03:
232 case eLanguageTypeC_plus_plus_11:
233 case eLanguageTypeC_plus_plus_14:
234 m_exception_language = eLanguageTypeC_plus_plus;
235 break;
236 case eLanguageTypeObjC:
237 m_exception_language = eLanguageTypeObjC;
238 break;
239 case eLanguageTypeObjC_plus_plus:
240 error.SetErrorStringWithFormat(
241 "Set exception breakpoints separately for c++ and objective-c");
242 break;
243 case eLanguageTypeUnknown:
244 error.SetErrorStringWithFormat(
245 "Unknown language type: '%s' for exception breakpoint",
246 option_arg);
247 break;
248 default:
249 error.SetErrorStringWithFormat(
250 "Unsupported language type: '%s' for exception breakpoint",
251 option_arg);
252 }
253 } break;
254
255 case 'f':
256 m_filenames.AppendIfUnique(FileSpec(option_arg, false));
257 break;
258
259 case 'F':
260 m_func_names.push_back(option_arg);
261 m_func_name_type_mask |= eFunctionNameTypeFull;
262 break;
263
264 case 'h': {
265 bool success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000266 m_catch_bp = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000267 if (!success)
268 error.SetErrorStringWithFormat(
269 "Invalid boolean value for on-catch option: '%s'", option_arg);
270 } break;
271
272 case 'H':
273 m_hardware = true;
274 break;
275
276 case 'i':
277 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
278 if (m_ignore_count == UINT32_MAX)
279 error.SetErrorStringWithFormat("invalid ignore count '%s'",
280 option_arg);
281 break;
282
283 case 'K': {
284 bool success;
285 bool value;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000286 value = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000287 if (value)
288 m_skip_prologue = eLazyBoolYes;
289 else
290 m_skip_prologue = eLazyBoolNo;
291
292 if (!success)
293 error.SetErrorStringWithFormat(
294 "Invalid boolean value for skip prologue option: '%s'",
295 option_arg);
296 } break;
297
298 case 'l': {
299 bool success;
300 m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success);
301 if (!success)
302 error.SetErrorStringWithFormat("invalid line number: %s.",
303 option_arg);
304 break;
305 }
306
307 case 'L':
Zachary Turner8cef4b02016-09-23 17:48:13 +0000308 m_language = Language::GetLanguageTypeFromString(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309 if (m_language == eLanguageTypeUnknown)
310 error.SetErrorStringWithFormat(
311 "Unknown language type: '%s' for breakpoint", option_arg);
312 break;
313
314 case 'm': {
315 bool success;
316 bool value;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000317 value = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000318 if (value)
319 m_move_to_nearest_code = eLazyBoolYes;
320 else
321 m_move_to_nearest_code = eLazyBoolNo;
322
323 if (!success)
324 error.SetErrorStringWithFormat(
325 "Invalid boolean value for move-to-nearest-code option: '%s'",
326 option_arg);
327 break;
328 }
329
330 case 'M':
331 m_func_names.push_back(option_arg);
332 m_func_name_type_mask |= eFunctionNameTypeMethod;
333 break;
334
335 case 'n':
336 m_func_names.push_back(option_arg);
337 m_func_name_type_mask |= eFunctionNameTypeAuto;
338 break;
339
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000340 case 'N': {
341 if (BreakpointID::StringIsBreakpointName(option_strref, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000342 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000343 else
344 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
345 option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000346 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000347 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000348
349 case 'R': {
350 lldb::addr_t tmp_offset_addr;
351 tmp_offset_addr =
352 Args::StringToAddress(execution_context, option_arg, 0, &error);
353 if (error.Success())
354 m_offset_addr = tmp_offset_addr;
355 } break;
356
357 case 'o':
358 m_one_shot = true;
359 break;
360
361 case 'O':
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000362 m_exception_extra_args.AppendArgument(llvm::StringRef("-O"));
363 m_exception_extra_args.AppendArgument(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364 break;
365
366 case 'p':
367 m_source_text_regexp.assign(option_arg);
368 break;
369
370 case 'q':
371 m_queue_name.assign(option_arg);
372 break;
373
374 case 'r':
375 m_func_regexp.assign(option_arg);
376 break;
377
378 case 's':
379 m_modules.AppendIfUnique(FileSpec(option_arg, false));
380 break;
381
382 case 'S':
383 m_func_names.push_back(option_arg);
384 m_func_name_type_mask |= eFunctionNameTypeSelector;
385 break;
386
387 case 't':
388 m_thread_id =
389 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
390 if (m_thread_id == LLDB_INVALID_THREAD_ID)
391 error.SetErrorStringWithFormat("invalid thread id string '%s'",
392 option_arg);
393 break;
394
395 case 'T':
396 m_thread_name.assign(option_arg);
397 break;
398
399 case 'w': {
400 bool success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000401 m_throw_bp = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000402 if (!success)
403 error.SetErrorStringWithFormat(
404 "Invalid boolean value for on-throw option: '%s'", option_arg);
405 } break;
406
407 case 'x':
408 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
409 if (m_thread_id == UINT32_MAX)
410 error.SetErrorStringWithFormat("invalid thread index string '%s'",
411 option_arg);
412 break;
413
414 case 'X':
415 m_source_regex_func_names.insert(option_arg);
416 break;
417
418 default:
419 error.SetErrorStringWithFormat("unrecognized option '%c'",
420 short_option);
421 break;
422 }
423
424 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000425 }
426
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427 void OptionParsingStarting(ExecutionContext *execution_context) override {
428 m_condition.clear();
429 m_filenames.Clear();
430 m_line_num = 0;
431 m_column = 0;
432 m_func_names.clear();
433 m_func_name_type_mask = eFunctionNameTypeNone;
434 m_func_regexp.clear();
435 m_source_text_regexp.clear();
436 m_modules.Clear();
437 m_load_addr = LLDB_INVALID_ADDRESS;
438 m_offset_addr = 0;
439 m_ignore_count = 0;
440 m_thread_id = LLDB_INVALID_THREAD_ID;
441 m_thread_index = UINT32_MAX;
442 m_thread_name.clear();
443 m_queue_name.clear();
444 m_catch_bp = false;
445 m_throw_bp = true;
446 m_hardware = false;
447 m_exception_language = eLanguageTypeUnknown;
448 m_language = lldb::eLanguageTypeUnknown;
449 m_skip_prologue = eLazyBoolCalculate;
450 m_one_shot = false;
451 m_use_dummy = false;
452 m_breakpoint_names.clear();
453 m_all_files = false;
454 m_exception_extra_args.Clear();
455 m_move_to_nearest_code = eLazyBoolCalculate;
456 m_source_regex_func_names.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000457 }
458
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000459 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000460 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000461 }
Jim Ingham5a988412012-06-08 21:56:10 +0000462
Kate Stoneb9c1b512016-09-06 20:57:50 +0000463 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000464
Kate Stoneb9c1b512016-09-06 20:57:50 +0000465 std::string m_condition;
466 FileSpecList m_filenames;
467 uint32_t m_line_num;
468 uint32_t m_column;
469 std::vector<std::string> m_func_names;
470 std::vector<std::string> m_breakpoint_names;
471 uint32_t m_func_name_type_mask;
472 std::string m_func_regexp;
473 std::string m_source_text_regexp;
474 FileSpecList m_modules;
475 lldb::addr_t m_load_addr;
476 lldb::addr_t m_offset_addr;
477 uint32_t m_ignore_count;
478 lldb::tid_t m_thread_id;
479 uint32_t m_thread_index;
480 std::string m_thread_name;
481 std::string m_queue_name;
482 bool m_catch_bp;
483 bool m_throw_bp;
484 bool m_hardware; // Request to use hardware breakpoints
485 lldb::LanguageType m_exception_language;
486 lldb::LanguageType m_language;
487 LazyBool m_skip_prologue;
488 bool m_one_shot;
489 bool m_use_dummy;
490 bool m_all_files;
491 Args m_exception_extra_args;
492 LazyBool m_move_to_nearest_code;
493 std::unordered_set<std::string> m_source_regex_func_names;
494 };
Jim Ingham5a988412012-06-08 21:56:10 +0000495
496protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000497 bool DoExecute(Args &command, CommandReturnObject &result) override {
498 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000499
Kate Stoneb9c1b512016-09-06 20:57:50 +0000500 if (target == nullptr) {
501 result.AppendError("Invalid target. Must set target before setting "
502 "breakpoints (see 'target create' command).");
503 result.SetStatus(eReturnStatusFailed);
504 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000505 }
506
Kate Stoneb9c1b512016-09-06 20:57:50 +0000507 // The following are the various types of breakpoints that could be set:
508 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
509 // 2). -a [-s -g] (setting breakpoint by address)
510 // 3). -n [-s -g] (setting breakpoint by function name)
511 // 4). -r [-s -g] (setting breakpoint by function name regular
512 // expression)
513 // 5). -p -f (setting a breakpoint by comparing a reg-exp
514 // to source text)
515 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
516 // given language.)
517
518 BreakpointSetType break_type = eSetTypeInvalid;
519
520 if (m_options.m_line_num != 0)
521 break_type = eSetTypeFileAndLine;
522 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
523 break_type = eSetTypeAddress;
524 else if (!m_options.m_func_names.empty())
525 break_type = eSetTypeFunctionName;
526 else if (!m_options.m_func_regexp.empty())
527 break_type = eSetTypeFunctionRegexp;
528 else if (!m_options.m_source_text_regexp.empty())
529 break_type = eSetTypeSourceRegexp;
530 else if (m_options.m_exception_language != eLanguageTypeUnknown)
531 break_type = eSetTypeException;
532
533 Breakpoint *bp = nullptr;
534 FileSpec module_spec;
535 const bool internal = false;
536
537 // If the user didn't specify skip-prologue, having an offset should turn
538 // that off.
539 if (m_options.m_offset_addr != 0 &&
540 m_options.m_skip_prologue == eLazyBoolCalculate)
541 m_options.m_skip_prologue = eLazyBoolNo;
542
543 switch (break_type) {
544 case eSetTypeFileAndLine: // Breakpoint by source position
545 {
546 FileSpec file;
547 const size_t num_files = m_options.m_filenames.GetSize();
548 if (num_files == 0) {
549 if (!GetDefaultFile(target, file, result)) {
550 result.AppendError("No file supplied and no default file available.");
551 result.SetStatus(eReturnStatusFailed);
552 return false;
553 }
554 } else if (num_files > 1) {
555 result.AppendError("Only one file at a time is allowed for file and "
556 "line breakpoints.");
557 result.SetStatus(eReturnStatusFailed);
558 return false;
559 } else
560 file = m_options.m_filenames.GetFileSpecAtIndex(0);
561
562 // Only check for inline functions if
563 LazyBool check_inlines = eLazyBoolCalculate;
564
565 bp = target
566 ->CreateBreakpoint(&(m_options.m_modules), file,
567 m_options.m_line_num, m_options.m_offset_addr,
568 check_inlines, m_options.m_skip_prologue,
569 internal, m_options.m_hardware,
570 m_options.m_move_to_nearest_code)
571 .get();
572 } break;
573
574 case eSetTypeAddress: // Breakpoint by address
575 {
576 // If a shared library has been specified, make an lldb_private::Address
577 // with the library, and
578 // use that. That way the address breakpoint will track the load location
579 // of the library.
580 size_t num_modules_specified = m_options.m_modules.GetSize();
581 if (num_modules_specified == 1) {
582 const FileSpec *file_spec =
583 m_options.m_modules.GetFileSpecPointerAtIndex(0);
584 bp = target
585 ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
586 internal, file_spec,
587 m_options.m_hardware)
588 .get();
589 } else if (num_modules_specified == 0) {
590 bp = target
591 ->CreateBreakpoint(m_options.m_load_addr, internal,
592 m_options.m_hardware)
593 .get();
594 } else {
595 result.AppendError("Only one shared library can be specified for "
596 "address breakpoints.");
597 result.SetStatus(eReturnStatusFailed);
598 return false;
599 }
600 break;
601 }
602 case eSetTypeFunctionName: // Breakpoint by function name
603 {
604 uint32_t name_type_mask = m_options.m_func_name_type_mask;
605
606 if (name_type_mask == 0)
607 name_type_mask = eFunctionNameTypeAuto;
608
609 bp = target
610 ->CreateBreakpoint(
611 &(m_options.m_modules), &(m_options.m_filenames),
612 m_options.m_func_names, name_type_mask, m_options.m_language,
613 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
614 m_options.m_hardware)
615 .get();
616 } break;
617
618 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
619 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000620 {
Zachary Turner95eae422016-09-21 16:01:28 +0000621 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000622 if (!regexp.IsValid()) {
623 char err_str[1024];
624 regexp.GetErrorAsCString(err_str, sizeof(err_str));
625 result.AppendErrorWithFormat(
626 "Function name regular expression could not be compiled: \"%s\"",
627 err_str);
628 result.SetStatus(eReturnStatusFailed);
629 return false;
630 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000631
Jim Inghame14dc262016-09-12 23:10:56 +0000632 bp = target
633 ->CreateFuncRegexBreakpoint(
634 &(m_options.m_modules), &(m_options.m_filenames), regexp,
635 m_options.m_language, m_options.m_skip_prologue, internal,
636 m_options.m_hardware)
637 .get();
638 }
639 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000640 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
641 {
642 const size_t num_files = m_options.m_filenames.GetSize();
643
644 if (num_files == 0 && !m_options.m_all_files) {
645 FileSpec file;
646 if (!GetDefaultFile(target, file, result)) {
647 result.AppendError(
648 "No files provided and could not find default file.");
649 result.SetStatus(eReturnStatusFailed);
650 return false;
651 } else {
652 m_options.m_filenames.Append(file);
653 }
654 }
655
Zachary Turner95eae422016-09-21 16:01:28 +0000656 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000657 if (!regexp.IsValid()) {
658 char err_str[1024];
659 regexp.GetErrorAsCString(err_str, sizeof(err_str));
660 result.AppendErrorWithFormat(
661 "Source text regular expression could not be compiled: \"%s\"",
662 err_str);
663 result.SetStatus(eReturnStatusFailed);
664 return false;
665 }
666 bp = target
667 ->CreateSourceRegexBreakpoint(
668 &(m_options.m_modules), &(m_options.m_filenames),
669 m_options.m_source_regex_func_names, regexp, internal,
670 m_options.m_hardware, m_options.m_move_to_nearest_code)
671 .get();
672 } break;
673 case eSetTypeException: {
674 Error precond_error;
675 bp = target
676 ->CreateExceptionBreakpoint(
677 m_options.m_exception_language, m_options.m_catch_bp,
678 m_options.m_throw_bp, internal,
679 &m_options.m_exception_extra_args, &precond_error)
680 .get();
681 if (precond_error.Fail()) {
682 result.AppendErrorWithFormat(
683 "Error setting extra exception arguments: %s",
684 precond_error.AsCString());
685 target->RemoveBreakpointByID(bp->GetID());
686 result.SetStatus(eReturnStatusFailed);
687 return false;
688 }
689 } break;
690 default:
691 break;
692 }
693
694 // Now set the various options that were passed in:
695 if (bp) {
696 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
697 bp->SetThreadID(m_options.m_thread_id);
698
699 if (m_options.m_thread_index != UINT32_MAX)
700 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
701
702 if (!m_options.m_thread_name.empty())
703 bp->GetOptions()->GetThreadSpec()->SetName(
704 m_options.m_thread_name.c_str());
705
706 if (!m_options.m_queue_name.empty())
707 bp->GetOptions()->GetThreadSpec()->SetQueueName(
708 m_options.m_queue_name.c_str());
709
710 if (m_options.m_ignore_count != 0)
711 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
712
713 if (!m_options.m_condition.empty())
714 bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
715
716 if (!m_options.m_breakpoint_names.empty()) {
Jim Inghamff9a91e2016-09-21 01:21:19 +0000717 Error name_error;
718 for (auto name : m_options.m_breakpoint_names) {
719 bp->AddName(name.c_str(), name_error);
720 if (name_error.Fail()) {
721 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
722 name.c_str());
723 target->RemoveBreakpointByID(bp->GetID());
724 result.SetStatus(eReturnStatusFailed);
725 return false;
726 }
727 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000728 }
729
730 bp->SetOneShot(m_options.m_one_shot);
731 }
732
733 if (bp) {
734 Stream &output_stream = result.GetOutputStream();
735 const bool show_locations = false;
736 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
737 show_locations);
738 if (target == m_interpreter.GetDebugger().GetDummyTarget())
739 output_stream.Printf("Breakpoint set in dummy target, will get copied "
740 "into future targets.\n");
741 else {
742 // Don't print out this warning for exception breakpoints. They can get
743 // set before the target
744 // is set, but we won't know how to actually set the breakpoint till we
745 // run.
746 if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) {
747 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
748 "actual locations.\n");
749 }
750 }
751 result.SetStatus(eReturnStatusSuccessFinishResult);
752 } else if (!bp) {
753 result.AppendError("Breakpoint creation failed: No breakpoint created.");
754 result.SetStatus(eReturnStatusFailed);
755 }
756
757 return result.Succeeded();
758 }
759
Jim Ingham5a988412012-06-08 21:56:10 +0000760private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000761 bool GetDefaultFile(Target *target, FileSpec &file,
762 CommandReturnObject &result) {
763 uint32_t default_line;
764 // First use the Source Manager's default file.
765 // Then use the current stack frame's file.
766 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
767 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
768 if (cur_frame == nullptr) {
769 result.AppendError(
770 "No selected frame to use to find the default file.");
771 result.SetStatus(eReturnStatusFailed);
772 return false;
773 } else if (!cur_frame->HasDebugInformation()) {
774 result.AppendError("Cannot use the selected frame to find the default "
775 "file, it has no debug info.");
776 result.SetStatus(eReturnStatusFailed);
777 return false;
778 } else {
779 const SymbolContext &sc =
780 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
781 if (sc.line_entry.file) {
782 file = sc.line_entry.file;
783 } else {
784 result.AppendError("Can't find the file for the selected frame to "
785 "use as the default file.");
786 result.SetStatus(eReturnStatusFailed);
787 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000788 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000789 }
Jim Ingham5a988412012-06-08 21:56:10 +0000790 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000791 return true;
792 }
793
794 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000795};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000796
Jim Ingham5a988412012-06-08 21:56:10 +0000797//-------------------------------------------------------------------------
798// CommandObjectBreakpointModify
799//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000800
801#pragma mark Modify::CommandOptions
802static OptionDefinition g_breakpoint_modify_options[] = {
803 // clang-format off
804 { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." },
805 { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." },
806 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." },
807 { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." },
808 { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." },
809 { LLDB_OPT_SET_ALL, 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." },
810 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
811 { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." },
812 { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." },
813 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
814 // clang-format on
815};
816
Jim Ingham5a988412012-06-08 21:56:10 +0000817#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000818
Kate Stoneb9c1b512016-09-06 20:57:50 +0000819class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000820public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000821 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
822 : CommandObjectParsed(interpreter, "breakpoint modify",
823 "Modify the options on a breakpoint or set of "
824 "breakpoints in the executable. "
825 "If no breakpoint is specified, acts on the last "
826 "created breakpoint. "
827 "With the exception of -e, -d and -i, passing an "
828 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000829 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000830 m_options() {
831 CommandArgumentEntry arg;
832 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
833 eArgTypeBreakpointIDRange);
834 // Add the entry for the first argument for this command to the object's
835 // arguments vector.
836 m_arguments.push_back(arg);
837 }
838
839 ~CommandObjectBreakpointModify() override = default;
840
841 Options *GetOptions() override { return &m_options; }
842
843 class CommandOptions : public Options {
844 public:
845 CommandOptions()
846 : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
847 m_thread_id_passed(false), m_thread_index(UINT32_MAX),
848 m_thread_index_passed(false), m_thread_name(), m_queue_name(),
849 m_condition(), m_one_shot(false), m_enable_passed(false),
850 m_enable_value(false), m_name_passed(false), m_queue_passed(false),
851 m_condition_passed(false), m_one_shot_passed(false),
852 m_use_dummy(false) {}
853
854 ~CommandOptions() override = default;
855
856 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
857 ExecutionContext *execution_context) override {
858 Error error;
859 const int short_option = m_getopt_table[option_idx].val;
860
861 switch (short_option) {
862 case 'c':
863 if (option_arg != nullptr)
864 m_condition.assign(option_arg);
865 else
866 m_condition.clear();
867 m_condition_passed = true;
868 break;
869 case 'd':
870 m_enable_passed = true;
871 m_enable_value = false;
872 break;
873 case 'D':
874 m_use_dummy = true;
875 break;
876 case 'e':
877 m_enable_passed = true;
878 m_enable_value = true;
879 break;
880 case 'i':
881 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
882 if (m_ignore_count == UINT32_MAX)
883 error.SetErrorStringWithFormat("invalid ignore count '%s'",
884 option_arg);
885 break;
886 case 'o': {
887 bool value, success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000888 value = Args::StringToBoolean(
889 llvm::StringRef::withNullAsEmpty(option_arg), false, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000890 if (success) {
891 m_one_shot_passed = true;
892 m_one_shot = value;
893 } else
894 error.SetErrorStringWithFormat(
895 "invalid boolean value '%s' passed for -o option", option_arg);
896 } break;
897 case 't':
898 if (option_arg[0] == '\0') {
899 m_thread_id = LLDB_INVALID_THREAD_ID;
900 m_thread_id_passed = true;
901 } else {
902 m_thread_id =
903 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
904 if (m_thread_id == LLDB_INVALID_THREAD_ID)
905 error.SetErrorStringWithFormat("invalid thread id string '%s'",
906 option_arg);
907 else
908 m_thread_id_passed = true;
909 }
910 break;
911 case 'T':
912 if (option_arg != nullptr)
913 m_thread_name.assign(option_arg);
914 else
915 m_thread_name.clear();
916 m_name_passed = true;
917 break;
918 case 'q':
919 if (option_arg != nullptr)
920 m_queue_name.assign(option_arg);
921 else
922 m_queue_name.clear();
923 m_queue_passed = true;
924 break;
925 case 'x':
926 if (option_arg[0] == '\n') {
927 m_thread_index = UINT32_MAX;
928 m_thread_index_passed = true;
929 } else {
930 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
931 if (m_thread_id == UINT32_MAX)
932 error.SetErrorStringWithFormat("invalid thread index string '%s'",
933 option_arg);
934 else
935 m_thread_index_passed = true;
936 }
937 break;
938 default:
939 error.SetErrorStringWithFormat("unrecognized option '%c'",
940 short_option);
941 break;
942 }
943
944 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000945 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000946
Kate Stoneb9c1b512016-09-06 20:57:50 +0000947 void OptionParsingStarting(ExecutionContext *execution_context) override {
948 m_ignore_count = 0;
949 m_thread_id = LLDB_INVALID_THREAD_ID;
950 m_thread_id_passed = false;
951 m_thread_index = UINT32_MAX;
952 m_thread_index_passed = false;
953 m_thread_name.clear();
954 m_queue_name.clear();
955 m_condition.clear();
956 m_one_shot = false;
957 m_enable_passed = false;
958 m_queue_passed = false;
959 m_name_passed = false;
960 m_condition_passed = false;
961 m_one_shot_passed = false;
962 m_use_dummy = false;
Jim Ingham5a988412012-06-08 21:56:10 +0000963 }
Johnny Chen7d49c9c2012-05-25 21:10:46 +0000964
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000965 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000966 return llvm::makeArrayRef(g_breakpoint_modify_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000967 }
Greg Claytone02b8502010-10-12 04:29:14 +0000968
Kate Stoneb9c1b512016-09-06 20:57:50 +0000969 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000970
Kate Stoneb9c1b512016-09-06 20:57:50 +0000971 uint32_t m_ignore_count;
972 lldb::tid_t m_thread_id;
973 bool m_thread_id_passed;
974 uint32_t m_thread_index;
975 bool m_thread_index_passed;
976 std::string m_thread_name;
977 std::string m_queue_name;
978 std::string m_condition;
979 bool m_one_shot;
980 bool m_enable_passed;
981 bool m_enable_value;
982 bool m_name_passed;
983 bool m_queue_passed;
984 bool m_condition_passed;
985 bool m_one_shot_passed;
986 bool m_use_dummy;
987 };
Jim Ingham5a988412012-06-08 21:56:10 +0000988
989protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000990 bool DoExecute(Args &command, CommandReturnObject &result) override {
991 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
992 if (target == nullptr) {
993 result.AppendError("Invalid target. No existing target or breakpoints.");
994 result.SetStatus(eReturnStatusFailed);
995 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000996 }
997
Kate Stoneb9c1b512016-09-06 20:57:50 +0000998 std::unique_lock<std::recursive_mutex> lock;
999 target->GetBreakpointList().GetListMutex(lock);
1000
1001 BreakpointIDList valid_bp_ids;
1002
1003 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1004 command, target, result, &valid_bp_ids);
1005
1006 if (result.Succeeded()) {
1007 const size_t count = valid_bp_ids.GetSize();
1008 for (size_t i = 0; i < count; ++i) {
1009 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1010
1011 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1012 Breakpoint *bp =
1013 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1014 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1015 BreakpointLocation *location =
1016 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
1017 if (location) {
1018 if (m_options.m_thread_id_passed)
1019 location->SetThreadID(m_options.m_thread_id);
1020
1021 if (m_options.m_thread_index_passed)
1022 location->SetThreadIndex(m_options.m_thread_index);
1023
1024 if (m_options.m_name_passed)
1025 location->SetThreadName(m_options.m_thread_name.c_str());
1026
1027 if (m_options.m_queue_passed)
1028 location->SetQueueName(m_options.m_queue_name.c_str());
1029
1030 if (m_options.m_ignore_count != 0)
1031 location->SetIgnoreCount(m_options.m_ignore_count);
1032
1033 if (m_options.m_enable_passed)
1034 location->SetEnabled(m_options.m_enable_value);
1035
1036 if (m_options.m_condition_passed)
1037 location->SetCondition(m_options.m_condition.c_str());
1038 }
1039 } else {
1040 if (m_options.m_thread_id_passed)
1041 bp->SetThreadID(m_options.m_thread_id);
1042
1043 if (m_options.m_thread_index_passed)
1044 bp->SetThreadIndex(m_options.m_thread_index);
1045
1046 if (m_options.m_name_passed)
1047 bp->SetThreadName(m_options.m_thread_name.c_str());
1048
1049 if (m_options.m_queue_passed)
1050 bp->SetQueueName(m_options.m_queue_name.c_str());
1051
1052 if (m_options.m_ignore_count != 0)
1053 bp->SetIgnoreCount(m_options.m_ignore_count);
1054
1055 if (m_options.m_enable_passed)
1056 bp->SetEnabled(m_options.m_enable_value);
1057
1058 if (m_options.m_condition_passed)
1059 bp->SetCondition(m_options.m_condition.c_str());
1060 }
1061 }
1062 }
1063 }
1064
1065 return result.Succeeded();
1066 }
1067
Jim Ingham5a988412012-06-08 21:56:10 +00001068private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001069 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001070};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001071
Jim Ingham5a988412012-06-08 21:56:10 +00001072//-------------------------------------------------------------------------
1073// CommandObjectBreakpointEnable
1074//-------------------------------------------------------------------------
1075#pragma mark Enable
1076
Kate Stoneb9c1b512016-09-06 20:57:50 +00001077class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001078public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001079 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1080 : CommandObjectParsed(interpreter, "enable",
1081 "Enable the specified disabled breakpoint(s). If "
1082 "no breakpoints are specified, enable all of them.",
1083 nullptr) {
1084 CommandArgumentEntry arg;
1085 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1086 eArgTypeBreakpointIDRange);
1087 // Add the entry for the first argument for this command to the object's
1088 // arguments vector.
1089 m_arguments.push_back(arg);
1090 }
Jim Ingham5a988412012-06-08 21:56:10 +00001091
Kate Stoneb9c1b512016-09-06 20:57:50 +00001092 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001093
1094protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001095 bool DoExecute(Args &command, CommandReturnObject &result) override {
1096 Target *target = GetSelectedOrDummyTarget();
1097 if (target == nullptr) {
1098 result.AppendError("Invalid target. No existing target or breakpoints.");
1099 result.SetStatus(eReturnStatusFailed);
1100 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001101 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001102
1103 std::unique_lock<std::recursive_mutex> lock;
1104 target->GetBreakpointList().GetListMutex(lock);
1105
1106 const BreakpointList &breakpoints = target->GetBreakpointList();
1107
1108 size_t num_breakpoints = breakpoints.GetSize();
1109
1110 if (num_breakpoints == 0) {
1111 result.AppendError("No breakpoints exist to be enabled.");
1112 result.SetStatus(eReturnStatusFailed);
1113 return false;
1114 }
1115
Zachary Turner11eb9c62016-10-05 20:03:37 +00001116 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001117 // No breakpoint selected; enable all currently set breakpoints.
1118 target->EnableAllBreakpoints();
1119 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1120 " breakpoints)\n",
1121 (uint64_t)num_breakpoints);
1122 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1123 } else {
1124 // Particular breakpoint selected; enable that breakpoint.
1125 BreakpointIDList valid_bp_ids;
1126 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1127 command, target, result, &valid_bp_ids);
1128
1129 if (result.Succeeded()) {
1130 int enable_count = 0;
1131 int loc_count = 0;
1132 const size_t count = valid_bp_ids.GetSize();
1133 for (size_t i = 0; i < count; ++i) {
1134 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1135
1136 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1137 Breakpoint *breakpoint =
1138 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1139 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1140 BreakpointLocation *location =
1141 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1142 if (location) {
1143 location->SetEnabled(true);
1144 ++loc_count;
1145 }
1146 } else {
1147 breakpoint->SetEnabled(true);
1148 ++enable_count;
1149 }
1150 }
1151 }
1152 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1153 enable_count + loc_count);
1154 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1155 }
1156 }
1157
1158 return result.Succeeded();
1159 }
Jim Ingham5a988412012-06-08 21:56:10 +00001160};
1161
1162//-------------------------------------------------------------------------
1163// CommandObjectBreakpointDisable
1164//-------------------------------------------------------------------------
1165#pragma mark Disable
1166
Kate Stoneb9c1b512016-09-06 20:57:50 +00001167class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001168public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001169 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1170 : CommandObjectParsed(
1171 interpreter, "breakpoint disable",
1172 "Disable the specified breakpoint(s) without deleting "
1173 "them. If none are specified, disable all "
1174 "breakpoints.",
1175 nullptr) {
1176 SetHelpLong(
1177 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001178If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001179 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001180
Kate Stone7428a182016-07-14 22:03:10 +00001181)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001182 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001183regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001184 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001185
1186 (lldb) break disable 1
1187 (lldb) break enable 1.1
1188
1189execution will NOT stop at location 1.1. To achieve that, type:
1190
1191 (lldb) break disable 1.*
1192 (lldb) break enable 1.1
1193
Kate Stone7428a182016-07-14 22:03:10 +00001194)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001195 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001196the second re-enables the first location.");
1197
Kate Stoneb9c1b512016-09-06 20:57:50 +00001198 CommandArgumentEntry arg;
1199 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1200 eArgTypeBreakpointIDRange);
1201 // Add the entry for the first argument for this command to the object's
1202 // arguments vector.
1203 m_arguments.push_back(arg);
1204 }
Jim Ingham5a988412012-06-08 21:56:10 +00001205
Kate Stoneb9c1b512016-09-06 20:57:50 +00001206 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001207
1208protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001209 bool DoExecute(Args &command, CommandReturnObject &result) override {
1210 Target *target = GetSelectedOrDummyTarget();
1211 if (target == nullptr) {
1212 result.AppendError("Invalid target. No existing target or breakpoints.");
1213 result.SetStatus(eReturnStatusFailed);
1214 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001215 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001216
1217 std::unique_lock<std::recursive_mutex> lock;
1218 target->GetBreakpointList().GetListMutex(lock);
1219
1220 const BreakpointList &breakpoints = target->GetBreakpointList();
1221 size_t num_breakpoints = breakpoints.GetSize();
1222
1223 if (num_breakpoints == 0) {
1224 result.AppendError("No breakpoints exist to be disabled.");
1225 result.SetStatus(eReturnStatusFailed);
1226 return false;
1227 }
1228
Zachary Turner11eb9c62016-10-05 20:03:37 +00001229 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001230 // No breakpoint selected; disable all currently set breakpoints.
1231 target->DisableAllBreakpoints();
1232 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1233 " breakpoints)\n",
1234 (uint64_t)num_breakpoints);
1235 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1236 } else {
1237 // Particular breakpoint selected; disable that breakpoint.
1238 BreakpointIDList valid_bp_ids;
1239
1240 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1241 command, target, result, &valid_bp_ids);
1242
1243 if (result.Succeeded()) {
1244 int disable_count = 0;
1245 int loc_count = 0;
1246 const size_t count = valid_bp_ids.GetSize();
1247 for (size_t i = 0; i < count; ++i) {
1248 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1249
1250 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1251 Breakpoint *breakpoint =
1252 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1253 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1254 BreakpointLocation *location =
1255 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1256 if (location) {
1257 location->SetEnabled(false);
1258 ++loc_count;
1259 }
1260 } else {
1261 breakpoint->SetEnabled(false);
1262 ++disable_count;
1263 }
1264 }
1265 }
1266 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1267 disable_count + loc_count);
1268 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1269 }
1270 }
1271
1272 return result.Succeeded();
1273 }
Jim Ingham5a988412012-06-08 21:56:10 +00001274};
1275
1276//-------------------------------------------------------------------------
1277// CommandObjectBreakpointList
1278//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001279
1280#pragma mark List::CommandOptions
1281static OptionDefinition g_breakpoint_list_options[] = {
1282 // clang-format off
1283 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1284 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
1285 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1286 // But I need to see it for now, and don't want to wait.
1287 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1288 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1289 { 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." },
1290 // clang-format on
1291};
1292
Jim Ingham5a988412012-06-08 21:56:10 +00001293#pragma mark List
1294
Kate Stoneb9c1b512016-09-06 20:57:50 +00001295class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001296public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001297 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1298 : CommandObjectParsed(
1299 interpreter, "breakpoint list",
1300 "List some or all breakpoints at configurable levels of detail.",
1301 nullptr),
1302 m_options() {
1303 CommandArgumentEntry arg;
1304 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001305
Kate Stoneb9c1b512016-09-06 20:57:50 +00001306 // Define the first (and only) variant of this arg.
1307 bp_id_arg.arg_type = eArgTypeBreakpointID;
1308 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001309
Kate Stoneb9c1b512016-09-06 20:57:50 +00001310 // There is only one variant this argument could be; put it into the
1311 // argument entry.
1312 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001313
Kate Stoneb9c1b512016-09-06 20:57:50 +00001314 // Push the data for the first argument into the m_arguments vector.
1315 m_arguments.push_back(arg);
1316 }
1317
1318 ~CommandObjectBreakpointList() override = default;
1319
1320 Options *GetOptions() override { return &m_options; }
1321
1322 class CommandOptions : public Options {
1323 public:
1324 CommandOptions()
1325 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001326 }
1327
Kate Stoneb9c1b512016-09-06 20:57:50 +00001328 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001329
Kate Stoneb9c1b512016-09-06 20:57:50 +00001330 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1331 ExecutionContext *execution_context) override {
1332 Error error;
1333 const int short_option = m_getopt_table[option_idx].val;
1334
1335 switch (short_option) {
1336 case 'b':
1337 m_level = lldb::eDescriptionLevelBrief;
1338 break;
1339 case 'D':
1340 m_use_dummy = true;
1341 break;
1342 case 'f':
1343 m_level = lldb::eDescriptionLevelFull;
1344 break;
1345 case 'v':
1346 m_level = lldb::eDescriptionLevelVerbose;
1347 break;
1348 case 'i':
1349 m_internal = true;
1350 break;
1351 default:
1352 error.SetErrorStringWithFormat("unrecognized option '%c'",
1353 short_option);
1354 break;
1355 }
1356
1357 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001358 }
Jim Ingham5a988412012-06-08 21:56:10 +00001359
Kate Stoneb9c1b512016-09-06 20:57:50 +00001360 void OptionParsingStarting(ExecutionContext *execution_context) override {
1361 m_level = lldb::eDescriptionLevelFull;
1362 m_internal = false;
1363 m_use_dummy = false;
1364 }
Jim Ingham5a988412012-06-08 21:56:10 +00001365
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001366 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001367 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001368 }
Jim Ingham5a988412012-06-08 21:56:10 +00001369
Kate Stoneb9c1b512016-09-06 20:57:50 +00001370 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001371
Kate Stoneb9c1b512016-09-06 20:57:50 +00001372 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001373
Kate Stoneb9c1b512016-09-06 20:57:50 +00001374 bool m_internal;
1375 bool m_use_dummy;
1376 };
Jim Ingham5a988412012-06-08 21:56:10 +00001377
1378protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001379 bool DoExecute(Args &command, CommandReturnObject &result) override {
1380 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001381
Kate Stoneb9c1b512016-09-06 20:57:50 +00001382 if (target == nullptr) {
1383 result.AppendError("Invalid target. No current target or breakpoints.");
1384 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1385 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001386 }
1387
Kate Stoneb9c1b512016-09-06 20:57:50 +00001388 const BreakpointList &breakpoints =
1389 target->GetBreakpointList(m_options.m_internal);
1390 std::unique_lock<std::recursive_mutex> lock;
1391 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1392
1393 size_t num_breakpoints = breakpoints.GetSize();
1394
1395 if (num_breakpoints == 0) {
1396 result.AppendMessage("No breakpoints currently set.");
1397 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1398 return true;
1399 }
1400
1401 Stream &output_stream = result.GetOutputStream();
1402
Zachary Turner11eb9c62016-10-05 20:03:37 +00001403 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001404 // No breakpoint selected; show info about all currently set breakpoints.
1405 result.AppendMessage("Current breakpoints:");
1406 for (size_t i = 0; i < num_breakpoints; ++i) {
1407 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1408 AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
1409 }
1410 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1411 } else {
1412 // Particular breakpoints selected; show info about that breakpoint.
1413 BreakpointIDList valid_bp_ids;
1414 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1415 command, target, result, &valid_bp_ids);
1416
1417 if (result.Succeeded()) {
1418 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1419 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1420 Breakpoint *breakpoint =
1421 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1422 AddBreakpointDescription(&output_stream, breakpoint,
1423 m_options.m_level);
1424 }
1425 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1426 } else {
1427 result.AppendError("Invalid breakpoint ID.");
1428 result.SetStatus(eReturnStatusFailed);
1429 }
1430 }
1431
1432 return result.Succeeded();
1433 }
1434
Jim Ingham5a988412012-06-08 21:56:10 +00001435private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001436 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001437};
1438
Jim Ingham5a988412012-06-08 21:56:10 +00001439//-------------------------------------------------------------------------
1440// CommandObjectBreakpointClear
1441//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001442#pragma mark Clear::CommandOptions
1443
1444static OptionDefinition g_breakpoint_clear_options[] = {
1445 // clang-format off
1446 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1447 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
1448 // clang-format on
1449};
1450
Jim Ingham5a988412012-06-08 21:56:10 +00001451#pragma mark Clear
1452
Kate Stoneb9c1b512016-09-06 20:57:50 +00001453class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001454public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001455 typedef enum BreakpointClearType {
1456 eClearTypeInvalid,
1457 eClearTypeFileAndLine
1458 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001459
Kate Stoneb9c1b512016-09-06 20:57:50 +00001460 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1461 : CommandObjectParsed(interpreter, "breakpoint clear",
1462 "Delete or disable breakpoints matching the "
1463 "specified source file and line.",
1464 "breakpoint clear <cmd-options>"),
1465 m_options() {}
1466
1467 ~CommandObjectBreakpointClear() override = default;
1468
1469 Options *GetOptions() override { return &m_options; }
1470
1471 class CommandOptions : public Options {
1472 public:
1473 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1474
1475 ~CommandOptions() override = default;
1476
1477 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1478 ExecutionContext *execution_context) override {
1479 Error error;
1480 const int short_option = m_getopt_table[option_idx].val;
1481
1482 switch (short_option) {
1483 case 'f':
1484 m_filename.assign(option_arg);
1485 break;
1486
1487 case 'l':
1488 m_line_num = StringConvert::ToUInt32(option_arg, 0);
1489 break;
1490
1491 default:
1492 error.SetErrorStringWithFormat("unrecognized option '%c'",
1493 short_option);
1494 break;
1495 }
1496
1497 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001498 }
1499
Kate Stoneb9c1b512016-09-06 20:57:50 +00001500 void OptionParsingStarting(ExecutionContext *execution_context) override {
1501 m_filename.clear();
1502 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001503 }
1504
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001505 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001506 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001507 }
Jim Ingham5a988412012-06-08 21:56:10 +00001508
Kate Stoneb9c1b512016-09-06 20:57:50 +00001509 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001510
Kate Stoneb9c1b512016-09-06 20:57:50 +00001511 std::string m_filename;
1512 uint32_t m_line_num;
1513 };
Jim Ingham5a988412012-06-08 21:56:10 +00001514
1515protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001516 bool DoExecute(Args &command, CommandReturnObject &result) override {
1517 Target *target = GetSelectedOrDummyTarget();
1518 if (target == nullptr) {
1519 result.AppendError("Invalid target. No existing target or breakpoints.");
1520 result.SetStatus(eReturnStatusFailed);
1521 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001522 }
1523
Kate Stoneb9c1b512016-09-06 20:57:50 +00001524 // The following are the various types of breakpoints that could be cleared:
1525 // 1). -f -l (clearing breakpoint by source location)
1526
1527 BreakpointClearType break_type = eClearTypeInvalid;
1528
1529 if (m_options.m_line_num != 0)
1530 break_type = eClearTypeFileAndLine;
1531
1532 std::unique_lock<std::recursive_mutex> lock;
1533 target->GetBreakpointList().GetListMutex(lock);
1534
1535 BreakpointList &breakpoints = target->GetBreakpointList();
1536 size_t num_breakpoints = breakpoints.GetSize();
1537
1538 // Early return if there's no breakpoint at all.
1539 if (num_breakpoints == 0) {
1540 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1541 result.SetStatus(eReturnStatusFailed);
1542 return result.Succeeded();
1543 }
1544
1545 // Find matching breakpoints and delete them.
1546
1547 // First create a copy of all the IDs.
1548 std::vector<break_id_t> BreakIDs;
1549 for (size_t i = 0; i < num_breakpoints; ++i)
1550 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1551
1552 int num_cleared = 0;
1553 StreamString ss;
1554 switch (break_type) {
1555 case eClearTypeFileAndLine: // Breakpoint by source position
1556 {
1557 const ConstString filename(m_options.m_filename.c_str());
1558 BreakpointLocationCollection loc_coll;
1559
1560 for (size_t i = 0; i < num_breakpoints; ++i) {
1561 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1562
1563 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1564 // If the collection size is 0, it's a full match and we can just
1565 // remove the breakpoint.
1566 if (loc_coll.GetSize() == 0) {
1567 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1568 ss.EOL();
1569 target->RemoveBreakpointByID(bp->GetID());
1570 ++num_cleared;
1571 }
1572 }
1573 }
1574 } break;
1575
1576 default:
1577 break;
1578 }
1579
1580 if (num_cleared > 0) {
1581 Stream &output_stream = result.GetOutputStream();
1582 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1583 output_stream << ss.GetData();
1584 output_stream.EOL();
1585 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1586 } else {
1587 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1588 result.SetStatus(eReturnStatusFailed);
1589 }
1590
1591 return result.Succeeded();
1592 }
1593
Jim Ingham5a988412012-06-08 21:56:10 +00001594private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001595 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001596};
1597
Jim Ingham5a988412012-06-08 21:56:10 +00001598//-------------------------------------------------------------------------
1599// CommandObjectBreakpointDelete
1600//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001601static OptionDefinition g_breakpoint_delete_options[] = {
1602 // clang-format off
1603 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1604 { 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." },
1605 // clang-format on
1606};
1607
Jim Ingham5a988412012-06-08 21:56:10 +00001608#pragma mark Delete
1609
Kate Stoneb9c1b512016-09-06 20:57:50 +00001610class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001611public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001612 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1613 : CommandObjectParsed(interpreter, "breakpoint delete",
1614 "Delete the specified breakpoint(s). If no "
1615 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001616 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001617 m_options() {
1618 CommandArgumentEntry arg;
1619 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1620 eArgTypeBreakpointIDRange);
1621 // Add the entry for the first argument for this command to the object's
1622 // arguments vector.
1623 m_arguments.push_back(arg);
1624 }
1625
1626 ~CommandObjectBreakpointDelete() override = default;
1627
1628 Options *GetOptions() override { return &m_options; }
1629
1630 class CommandOptions : public Options {
1631 public:
1632 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1633
1634 ~CommandOptions() override = default;
1635
1636 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1637 ExecutionContext *execution_context) override {
1638 Error error;
1639 const int short_option = m_getopt_table[option_idx].val;
1640
1641 switch (short_option) {
1642 case 'f':
1643 m_force = true;
1644 break;
1645
1646 case 'D':
1647 m_use_dummy = true;
1648 break;
1649
1650 default:
1651 error.SetErrorStringWithFormat("unrecognized option '%c'",
1652 short_option);
1653 break;
1654 }
1655
1656 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001657 }
1658
Kate Stoneb9c1b512016-09-06 20:57:50 +00001659 void OptionParsingStarting(ExecutionContext *execution_context) override {
1660 m_use_dummy = false;
1661 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001662 }
1663
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001664 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001665 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001666 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001667
Kate Stoneb9c1b512016-09-06 20:57:50 +00001668 // Instance variables to hold the values for command options.
1669 bool m_use_dummy;
1670 bool m_force;
1671 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001672
Jim Ingham5a988412012-06-08 21:56:10 +00001673protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001674 bool DoExecute(Args &command, CommandReturnObject &result) override {
1675 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001676
Kate Stoneb9c1b512016-09-06 20:57:50 +00001677 if (target == nullptr) {
1678 result.AppendError("Invalid target. No existing target or breakpoints.");
1679 result.SetStatus(eReturnStatusFailed);
1680 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001681 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001682
Kate Stoneb9c1b512016-09-06 20:57:50 +00001683 std::unique_lock<std::recursive_mutex> lock;
1684 target->GetBreakpointList().GetListMutex(lock);
1685
1686 const BreakpointList &breakpoints = target->GetBreakpointList();
1687
1688 size_t num_breakpoints = breakpoints.GetSize();
1689
1690 if (num_breakpoints == 0) {
1691 result.AppendError("No breakpoints exist to be deleted.");
1692 result.SetStatus(eReturnStatusFailed);
1693 return false;
1694 }
1695
Zachary Turner11eb9c62016-10-05 20:03:37 +00001696 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001697 if (!m_options.m_force &&
1698 !m_interpreter.Confirm(
1699 "About to delete all breakpoints, do you want to do that?",
1700 true)) {
1701 result.AppendMessage("Operation cancelled...");
1702 } else {
1703 target->RemoveAllBreakpoints();
1704 result.AppendMessageWithFormat(
1705 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1706 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1707 }
1708 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1709 } else {
1710 // Particular breakpoint selected; disable that breakpoint.
1711 BreakpointIDList valid_bp_ids;
1712 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1713 command, target, result, &valid_bp_ids);
1714
1715 if (result.Succeeded()) {
1716 int delete_count = 0;
1717 int disable_count = 0;
1718 const size_t count = valid_bp_ids.GetSize();
1719 for (size_t i = 0; i < count; ++i) {
1720 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1721
1722 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1723 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1724 Breakpoint *breakpoint =
1725 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1726 BreakpointLocation *location =
1727 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1728 // It makes no sense to try to delete individual locations, so we
1729 // disable them instead.
1730 if (location) {
1731 location->SetEnabled(false);
1732 ++disable_count;
1733 }
1734 } else {
1735 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1736 ++delete_count;
1737 }
1738 }
1739 }
1740 result.AppendMessageWithFormat(
1741 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1742 delete_count, disable_count);
1743 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1744 }
1745 }
1746 return result.Succeeded();
1747 }
1748
Jim Ingham33df7cd2014-12-06 01:28:03 +00001749private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001750 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001751};
1752
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001753//-------------------------------------------------------------------------
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001754// CommandObjectBreakpointName
1755//-------------------------------------------------------------------------
1756
Kate Stone7428a182016-07-14 22:03:10 +00001757static OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001758 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001759 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1760 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1761 {LLDB_OPT_SET_ALL, 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."},
Kate Stoneb9c1b512016-09-06 20:57:50 +00001762 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001763};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001764class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001765public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001766 BreakpointNameOptionGroup()
1767 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1768 }
1769
1770 ~BreakpointNameOptionGroup() override = default;
1771
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001772 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001773 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001774 }
1775
Zachary Turner8cef4b02016-09-23 17:48:13 +00001776 Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_value,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001777 ExecutionContext *execution_context) override {
1778 Error error;
1779 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1780
1781 switch (short_option) {
1782 case 'N':
Zachary Turner8cef4b02016-09-23 17:48:13 +00001783 if (BreakpointID::StringIsBreakpointName(option_value, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001784 error.Success())
Zachary Turner8cef4b02016-09-23 17:48:13 +00001785 m_name.SetValueFromString(option_value);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001786 break;
1787
1788 case 'B':
1789 if (m_breakpoint.SetValueFromString(option_value).Fail())
1790 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001791 "unrecognized value \"%s\" for breakpoint",
1792 option_value.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001793 break;
1794 case 'D':
1795 if (m_use_dummy.SetValueFromString(option_value).Fail())
1796 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001797 "unrecognized value \"%s\" for use-dummy",
1798 option_value.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001799 break;
1800
1801 default:
1802 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1803 short_option);
1804 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001805 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001806 return error;
1807 }
Zachary Turner8cef4b02016-09-23 17:48:13 +00001808 Error SetOptionValue(uint32_t, const char *, ExecutionContext *) = delete;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001809
Kate Stoneb9c1b512016-09-06 20:57:50 +00001810 void OptionParsingStarting(ExecutionContext *execution_context) override {
1811 m_name.Clear();
1812 m_breakpoint.Clear();
1813 m_use_dummy.Clear();
1814 m_use_dummy.SetDefaultValue(false);
1815 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001816
Kate Stoneb9c1b512016-09-06 20:57:50 +00001817 OptionValueString m_name;
1818 OptionValueUInt64 m_breakpoint;
1819 OptionValueBoolean m_use_dummy;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001820};
1821
Kate Stoneb9c1b512016-09-06 20:57:50 +00001822class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001823public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001824 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1825 : CommandObjectParsed(
1826 interpreter, "add", "Add a name to the breakpoints provided.",
1827 "breakpoint name add <command-options> <breakpoint-id-list>"),
1828 m_name_options(), m_option_group() {
1829 // Create the first variant for the first (and only) argument for this
1830 // command.
1831 CommandArgumentEntry arg1;
1832 CommandArgumentData id_arg;
1833 id_arg.arg_type = eArgTypeBreakpointID;
1834 id_arg.arg_repetition = eArgRepeatOptional;
1835 arg1.push_back(id_arg);
1836 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001837
Kate Stoneb9c1b512016-09-06 20:57:50 +00001838 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1839 m_option_group.Finalize();
1840 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001841
Kate Stoneb9c1b512016-09-06 20:57:50 +00001842 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001843
Kate Stoneb9c1b512016-09-06 20:57:50 +00001844 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001845
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001846protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001847 bool DoExecute(Args &command, CommandReturnObject &result) override {
1848 if (!m_name_options.m_name.OptionWasSet()) {
1849 result.SetError("No name option provided.");
1850 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001851 }
1852
Kate Stoneb9c1b512016-09-06 20:57:50 +00001853 Target *target =
1854 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1855
1856 if (target == nullptr) {
1857 result.AppendError("Invalid target. No existing target or breakpoints.");
1858 result.SetStatus(eReturnStatusFailed);
1859 return false;
1860 }
1861
1862 std::unique_lock<std::recursive_mutex> lock;
1863 target->GetBreakpointList().GetListMutex(lock);
1864
1865 const BreakpointList &breakpoints = target->GetBreakpointList();
1866
1867 size_t num_breakpoints = breakpoints.GetSize();
1868 if (num_breakpoints == 0) {
1869 result.SetError("No breakpoints, cannot add names.");
1870 result.SetStatus(eReturnStatusFailed);
1871 return false;
1872 }
1873
1874 // Particular breakpoint selected; disable that breakpoint.
1875 BreakpointIDList valid_bp_ids;
1876 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1877 command, target, result, &valid_bp_ids);
1878
1879 if (result.Succeeded()) {
1880 if (valid_bp_ids.GetSize() == 0) {
1881 result.SetError("No breakpoints specified, cannot add names.");
1882 result.SetStatus(eReturnStatusFailed);
1883 return false;
1884 }
1885 size_t num_valid_ids = valid_bp_ids.GetSize();
1886 for (size_t index = 0; index < num_valid_ids; index++) {
1887 lldb::break_id_t bp_id =
1888 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1889 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1890 Error error; // We don't need to check the error here, since the option
1891 // parser checked it...
1892 bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
1893 }
1894 }
1895
1896 return true;
1897 }
1898
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001899private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001900 BreakpointNameOptionGroup m_name_options;
1901 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001902};
1903
Kate Stoneb9c1b512016-09-06 20:57:50 +00001904class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001905public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001906 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1907 : CommandObjectParsed(
1908 interpreter, "delete",
1909 "Delete a name from the breakpoints provided.",
1910 "breakpoint name delete <command-options> <breakpoint-id-list>"),
1911 m_name_options(), m_option_group() {
1912 // Create the first variant for the first (and only) argument for this
1913 // command.
1914 CommandArgumentEntry arg1;
1915 CommandArgumentData id_arg;
1916 id_arg.arg_type = eArgTypeBreakpointID;
1917 id_arg.arg_repetition = eArgRepeatOptional;
1918 arg1.push_back(id_arg);
1919 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001920
Kate Stoneb9c1b512016-09-06 20:57:50 +00001921 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1922 m_option_group.Finalize();
1923 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001924
Kate Stoneb9c1b512016-09-06 20:57:50 +00001925 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001926
Kate Stoneb9c1b512016-09-06 20:57:50 +00001927 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001928
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001929protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001930 bool DoExecute(Args &command, CommandReturnObject &result) override {
1931 if (!m_name_options.m_name.OptionWasSet()) {
1932 result.SetError("No name option provided.");
1933 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001934 }
1935
Kate Stoneb9c1b512016-09-06 20:57:50 +00001936 Target *target =
1937 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1938
1939 if (target == nullptr) {
1940 result.AppendError("Invalid target. No existing target or breakpoints.");
1941 result.SetStatus(eReturnStatusFailed);
1942 return false;
1943 }
1944
1945 std::unique_lock<std::recursive_mutex> lock;
1946 target->GetBreakpointList().GetListMutex(lock);
1947
1948 const BreakpointList &breakpoints = target->GetBreakpointList();
1949
1950 size_t num_breakpoints = breakpoints.GetSize();
1951 if (num_breakpoints == 0) {
1952 result.SetError("No breakpoints, cannot delete names.");
1953 result.SetStatus(eReturnStatusFailed);
1954 return false;
1955 }
1956
1957 // Particular breakpoint selected; disable that breakpoint.
1958 BreakpointIDList valid_bp_ids;
1959 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1960 command, target, result, &valid_bp_ids);
1961
1962 if (result.Succeeded()) {
1963 if (valid_bp_ids.GetSize() == 0) {
1964 result.SetError("No breakpoints specified, cannot delete names.");
1965 result.SetStatus(eReturnStatusFailed);
1966 return false;
1967 }
1968 size_t num_valid_ids = valid_bp_ids.GetSize();
1969 for (size_t index = 0; index < num_valid_ids; index++) {
1970 lldb::break_id_t bp_id =
1971 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1972 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1973 bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
1974 }
1975 }
1976
1977 return true;
1978 }
1979
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001980private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001981 BreakpointNameOptionGroup m_name_options;
1982 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001983};
1984
Kate Stoneb9c1b512016-09-06 20:57:50 +00001985class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001986public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001987 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1988 : CommandObjectParsed(interpreter, "list",
1989 "List either the names for a breakpoint or the "
1990 "breakpoints for a given name.",
1991 "breakpoint name list <command-options>"),
1992 m_name_options(), m_option_group() {
1993 m_option_group.Append(&m_name_options);
1994 m_option_group.Finalize();
1995 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001996
Kate Stoneb9c1b512016-09-06 20:57:50 +00001997 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001998
Kate Stoneb9c1b512016-09-06 20:57:50 +00001999 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002000
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002001protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002002 bool DoExecute(Args &command, CommandReturnObject &result) override {
2003 Target *target =
2004 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002005
Kate Stoneb9c1b512016-09-06 20:57:50 +00002006 if (target == nullptr) {
2007 result.AppendError("Invalid target. No existing target or breakpoints.");
2008 result.SetStatus(eReturnStatusFailed);
2009 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002010 }
2011
Kate Stoneb9c1b512016-09-06 20:57:50 +00002012 if (m_name_options.m_name.OptionWasSet()) {
2013 const char *name = m_name_options.m_name.GetCurrentValue();
2014 std::unique_lock<std::recursive_mutex> lock;
2015 target->GetBreakpointList().GetListMutex(lock);
2016
2017 BreakpointList &breakpoints = target->GetBreakpointList();
2018 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2019 if (bp_sp->MatchesName(name)) {
2020 StreamString s;
2021 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2022 s.EOL();
2023 result.AppendMessage(s.GetData());
2024 }
2025 }
2026
2027 } else if (m_name_options.m_breakpoint.OptionWasSet()) {
2028 BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(
2029 m_name_options.m_breakpoint.GetCurrentValue());
2030 if (bp_sp) {
2031 std::vector<std::string> names;
2032 bp_sp->GetNames(names);
2033 result.AppendMessage("Names:");
2034 for (auto name : names)
2035 result.AppendMessageWithFormat(" %s\n", name.c_str());
2036 } else {
2037 result.AppendErrorWithFormat(
2038 "Could not find breakpoint %" PRId64 ".\n",
2039 m_name_options.m_breakpoint.GetCurrentValue());
2040 result.SetStatus(eReturnStatusFailed);
2041 return false;
2042 }
2043 } else {
2044 result.SetError("Must specify -N or -B option to list.");
2045 result.SetStatus(eReturnStatusFailed);
2046 return false;
2047 }
2048 return true;
2049 }
2050
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002051private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002052 BreakpointNameOptionGroup m_name_options;
2053 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002054};
2055
2056//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002057// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002058//-------------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00002059class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002060public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002061 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2062 : CommandObjectMultiword(
2063 interpreter, "name", "Commands to manage name tags for breakpoints",
2064 "breakpoint name <subcommand> [<command-options>]") {
2065 CommandObjectSP add_command_object(
2066 new CommandObjectBreakpointNameAdd(interpreter));
2067 CommandObjectSP delete_command_object(
2068 new CommandObjectBreakpointNameDelete(interpreter));
2069 CommandObjectSP list_command_object(
2070 new CommandObjectBreakpointNameList(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002071
Kate Stoneb9c1b512016-09-06 20:57:50 +00002072 LoadSubCommand("add", add_command_object);
2073 LoadSubCommand("delete", delete_command_object);
2074 LoadSubCommand("list", list_command_object);
2075 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002076
Kate Stoneb9c1b512016-09-06 20:57:50 +00002077 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002078};
2079
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002080//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002081// CommandObjectBreakpointRead
2082//-------------------------------------------------------------------------
Jim Ingham3acdf382016-09-22 22:20:28 +00002083#pragma mark Read::CommandOptions
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002084static OptionDefinition g_breakpoint_read_options[] = {
2085 // clang-format off
Jim Ingham3acdf382016-09-22 22:20:28 +00002086 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2087 {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 +00002088 // clang-format on
2089};
2090
2091#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002092
2093class CommandObjectBreakpointRead : public CommandObjectParsed {
2094public:
2095 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2096 : CommandObjectParsed(interpreter, "breakpoint read",
2097 "Read and set the breakpoints previously saved to "
2098 "a file with \"breakpoint write\". ",
2099 nullptr),
2100 m_options() {
2101 CommandArgumentEntry arg;
2102 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2103 eArgTypeBreakpointIDRange);
2104 // Add the entry for the first argument for this command to the object's
2105 // arguments vector.
2106 m_arguments.push_back(arg);
2107 }
2108
2109 ~CommandObjectBreakpointRead() override = default;
2110
2111 Options *GetOptions() override { return &m_options; }
2112
2113 class CommandOptions : public Options {
2114 public:
2115 CommandOptions() : Options() {}
2116
2117 ~CommandOptions() override = default;
2118
2119 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2120 ExecutionContext *execution_context) override {
2121 Error error;
2122 const int short_option = m_getopt_table[option_idx].val;
2123
2124 switch (short_option) {
2125 case 'f':
2126 m_filename.assign(option_arg);
2127 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002128 case 'N': {
2129 Error name_error;
2130 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2131 name_error)) {
2132 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2133 name_error.AsCString());
2134 }
2135 m_names.push_back(option_arg);
2136 break;
2137 }
Jim Inghame14dc262016-09-12 23:10:56 +00002138 default:
2139 error.SetErrorStringWithFormat("unrecognized option '%c'",
2140 short_option);
2141 break;
2142 }
2143
2144 return error;
2145 }
2146
2147 void OptionParsingStarting(ExecutionContext *execution_context) override {
2148 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002149 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002150 }
2151
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002152 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002153 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002154 }
Jim Inghame14dc262016-09-12 23:10:56 +00002155
2156 // Instance variables to hold the values for command options.
2157
2158 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002159 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002160 };
2161
2162protected:
2163 bool DoExecute(Args &command, CommandReturnObject &result) override {
2164 Target *target = GetSelectedOrDummyTarget();
2165 if (target == nullptr) {
2166 result.AppendError("Invalid target. No existing target or breakpoints.");
2167 result.SetStatus(eReturnStatusFailed);
2168 return false;
2169 }
2170
Jim Ingham3acdf382016-09-22 22:20:28 +00002171 std::unique_lock<std::recursive_mutex> lock;
2172 target->GetBreakpointList().GetListMutex(lock);
2173
Jim Inghame14dc262016-09-12 23:10:56 +00002174 FileSpec input_spec(m_options.m_filename, true);
Jim Ingham01f16662016-09-14 19:07:35 +00002175 BreakpointIDList new_bps;
Jim Ingham3acdf382016-09-22 22:20:28 +00002176 Error error = target->CreateBreakpointsFromFile(input_spec,
2177 m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002178
Jim Inghame14dc262016-09-12 23:10:56 +00002179 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002180 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002181 result.SetStatus(eReturnStatusFailed);
2182 return false;
2183 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002184
2185 Stream &output_stream = result.GetOutputStream();
2186
2187 size_t num_breakpoints = new_bps.GetSize();
2188 if (num_breakpoints == 0) {
2189 result.AppendMessage("No breakpoints added.");
2190 } else {
2191 // No breakpoint selected; show info about all currently set breakpoints.
2192 result.AppendMessage("New breakpoints:");
2193 for (size_t i = 0; i < num_breakpoints; ++i) {
2194 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2195 Breakpoint *bp = target->GetBreakpointList()
2196 .FindBreakpointByID(bp_id.GetBreakpointID())
2197 .get();
2198 if (bp)
2199 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2200 false);
2201 }
2202 }
Jim Inghame14dc262016-09-12 23:10:56 +00002203 return result.Succeeded();
2204 }
2205
2206private:
2207 CommandOptions m_options;
2208};
2209
Jim Inghame14dc262016-09-12 23:10:56 +00002210//-------------------------------------------------------------------------
2211// CommandObjectBreakpointWrite
2212//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002213#pragma mark Write::CommandOptions
2214static OptionDefinition g_breakpoint_write_options[] = {
2215 // clang-format off
Jim Ingham2d3628e2016-09-22 23:42:42 +00002216 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2217 { 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 +00002218 // clang-format on
2219};
2220
2221#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002222class CommandObjectBreakpointWrite : public CommandObjectParsed {
2223public:
2224 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2225 : CommandObjectParsed(interpreter, "breakpoint write",
2226 "Write the breakpoints listed to a file that can "
2227 "be read in with \"breakpoint read\". "
2228 "If given no arguments, writes all breakpoints.",
2229 nullptr),
2230 m_options() {
2231 CommandArgumentEntry arg;
2232 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2233 eArgTypeBreakpointIDRange);
2234 // Add the entry for the first argument for this command to the object's
2235 // arguments vector.
2236 m_arguments.push_back(arg);
2237 }
2238
2239 ~CommandObjectBreakpointWrite() override = default;
2240
2241 Options *GetOptions() override { return &m_options; }
2242
2243 class CommandOptions : public Options {
2244 public:
2245 CommandOptions() : Options() {}
2246
2247 ~CommandOptions() override = default;
2248
2249 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2250 ExecutionContext *execution_context) override {
2251 Error error;
2252 const int short_option = m_getopt_table[option_idx].val;
2253
2254 switch (short_option) {
2255 case 'f':
2256 m_filename.assign(option_arg);
2257 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002258 case 'a':
2259 m_append = true;
2260 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002261 default:
2262 error.SetErrorStringWithFormat("unrecognized option '%c'",
2263 short_option);
2264 break;
2265 }
2266
2267 return error;
2268 }
2269
2270 void OptionParsingStarting(ExecutionContext *execution_context) override {
2271 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002272 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002273 }
2274
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002275 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002276 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002277 }
Jim Inghame14dc262016-09-12 23:10:56 +00002278
2279 // Instance variables to hold the values for command options.
2280
2281 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002282 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002283 };
2284
2285protected:
2286 bool DoExecute(Args &command, CommandReturnObject &result) override {
2287 Target *target = GetSelectedOrDummyTarget();
2288 if (target == nullptr) {
2289 result.AppendError("Invalid target. No existing target or breakpoints.");
2290 result.SetStatus(eReturnStatusFailed);
2291 return false;
2292 }
2293
Jim Inghame14dc262016-09-12 23:10:56 +00002294 std::unique_lock<std::recursive_mutex> lock;
2295 target->GetBreakpointList().GetListMutex(lock);
2296
Jim Ingham01f16662016-09-14 19:07:35 +00002297 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002298 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002299 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2300 command, target, result, &valid_bp_ids);
2301
Jim Ingham01f16662016-09-14 19:07:35 +00002302 if (!result.Succeeded()) {
2303 result.SetStatus(eReturnStatusFailed);
2304 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002305 }
2306 }
Jim Ingham01f16662016-09-14 19:07:35 +00002307 Error error = target->SerializeBreakpointsToFile(
Malcolm Parsons771ef6d2016-11-02 20:34:10 +00002308 FileSpec(m_options.m_filename, true), valid_bp_ids, m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002309 if (!error.Success()) {
2310 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2311 error.AsCString());
2312 result.SetStatus(eReturnStatusFailed);
2313 }
Jim Inghame14dc262016-09-12 23:10:56 +00002314 return result.Succeeded();
2315 }
2316
2317private:
2318 CommandOptions m_options;
2319};
2320
Jim Inghame14dc262016-09-12 23:10:56 +00002321//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002322// CommandObjectMultiwordBreakpoint
2323//-------------------------------------------------------------------------
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002324#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002325
Kate Stoneb9c1b512016-09-06 20:57:50 +00002326CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2327 CommandInterpreter &interpreter)
2328 : CommandObjectMultiword(
2329 interpreter, "breakpoint",
2330 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2331 "breakpoint <subcommand> [<command-options>]") {
2332 CommandObjectSP list_command_object(
2333 new CommandObjectBreakpointList(interpreter));
2334 CommandObjectSP enable_command_object(
2335 new CommandObjectBreakpointEnable(interpreter));
2336 CommandObjectSP disable_command_object(
2337 new CommandObjectBreakpointDisable(interpreter));
2338 CommandObjectSP clear_command_object(
2339 new CommandObjectBreakpointClear(interpreter));
2340 CommandObjectSP delete_command_object(
2341 new CommandObjectBreakpointDelete(interpreter));
2342 CommandObjectSP set_command_object(
2343 new CommandObjectBreakpointSet(interpreter));
2344 CommandObjectSP command_command_object(
2345 new CommandObjectBreakpointCommand(interpreter));
2346 CommandObjectSP modify_command_object(
2347 new CommandObjectBreakpointModify(interpreter));
2348 CommandObjectSP name_command_object(
2349 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002350 CommandObjectSP write_command_object(
2351 new CommandObjectBreakpointWrite(interpreter));
2352 CommandObjectSP read_command_object(
2353 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002354
Kate Stoneb9c1b512016-09-06 20:57:50 +00002355 list_command_object->SetCommandName("breakpoint list");
2356 enable_command_object->SetCommandName("breakpoint enable");
2357 disable_command_object->SetCommandName("breakpoint disable");
2358 clear_command_object->SetCommandName("breakpoint clear");
2359 delete_command_object->SetCommandName("breakpoint delete");
2360 set_command_object->SetCommandName("breakpoint set");
2361 command_command_object->SetCommandName("breakpoint command");
2362 modify_command_object->SetCommandName("breakpoint modify");
2363 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002364 write_command_object->SetCommandName("breakpoint write");
2365 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002366
Kate Stoneb9c1b512016-09-06 20:57:50 +00002367 LoadSubCommand("list", list_command_object);
2368 LoadSubCommand("enable", enable_command_object);
2369 LoadSubCommand("disable", disable_command_object);
2370 LoadSubCommand("clear", clear_command_object);
2371 LoadSubCommand("delete", delete_command_object);
2372 LoadSubCommand("set", set_command_object);
2373 LoadSubCommand("command", command_command_object);
2374 LoadSubCommand("modify", modify_command_object);
2375 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002376 LoadSubCommand("write", write_command_object);
2377 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002378}
2379
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002380CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002381
Kate Stoneb9c1b512016-09-06 20:57:50 +00002382void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2383 bool allow_locations,
2384 CommandReturnObject &result,
2385 BreakpointIDList *valid_ids) {
2386 // args can be strings representing 1). integers (for breakpoint ids)
2387 // 2). the full breakpoint & location
2388 // canonical representation
2389 // 3). the word "to" or a hyphen,
2390 // representing a range (in which case there
2391 // had *better* be an entry both before &
2392 // after of one of the first two types.
2393 // 4). A breakpoint name
2394 // If args is empty, we will use the last created breakpoint (if there is
2395 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002396
Kate Stoneb9c1b512016-09-06 20:57:50 +00002397 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002398
Zachary Turner11eb9c62016-10-05 20:03:37 +00002399 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002400 if (target->GetLastCreatedBreakpoint()) {
2401 valid_ids->AddBreakpointID(BreakpointID(
2402 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2403 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2404 } else {
2405 result.AppendError(
2406 "No breakpoint specified and no last created breakpoint.");
2407 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002408 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002409 return;
2410 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002411
Kate Stoneb9c1b512016-09-06 20:57:50 +00002412 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2413 // directly from the old ARGS to
2414 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead
2415 // generate a list of strings for
2416 // all the breakpoint ids in the range, and shove all of those breakpoint id
2417 // strings into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002418
Kate Stoneb9c1b512016-09-06 20:57:50 +00002419 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2420 result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002421
Kate Stoneb9c1b512016-09-06 20:57:50 +00002422 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2423 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002424
Kate Stoneb9c1b512016-09-06 20:57:50 +00002425 valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
2426 temp_args.GetArgumentCount(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002427
Kate Stoneb9c1b512016-09-06 20:57:50 +00002428 // At this point, all of the breakpoint ids that the user passed in have been
2429 // converted to breakpoint IDs
2430 // and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002431
Kate Stoneb9c1b512016-09-06 20:57:50 +00002432 if (result.Succeeded()) {
2433 // Now that we've converted everything from args into a list of breakpoint
2434 // ids, go through our tentative list
2435 // of breakpoint id's and verify that they correspond to valid/currently set
2436 // breakpoints.
2437
2438 const size_t count = valid_ids->GetSize();
2439 for (size_t i = 0; i < count; ++i) {
2440 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2441 Breakpoint *breakpoint =
2442 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2443 if (breakpoint != nullptr) {
2444 const size_t num_locations = breakpoint->GetNumLocations();
2445 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2446 StreamString id_str;
2447 BreakpointID::GetCanonicalReference(
2448 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2449 i = valid_ids->GetSize() + 1;
2450 result.AppendErrorWithFormat(
2451 "'%s' is not a currently valid breakpoint/location id.\n",
2452 id_str.GetData());
2453 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002454 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002455 } else {
2456 i = valid_ids->GetSize() + 1;
2457 result.AppendErrorWithFormat(
2458 "'%d' is not a currently valid breakpoint ID.\n",
2459 cur_bp_id.GetBreakpointID());
2460 result.SetStatus(eReturnStatusFailed);
2461 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002462 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002463 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002464}