blob: cb6d1d83907ca32b9b1e03bc5c8c1a849bb83993 [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': {
220 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
221
222 switch (language) {
223 case eLanguageTypeC89:
224 case eLanguageTypeC:
225 case eLanguageTypeC99:
226 case eLanguageTypeC11:
227 m_exception_language = eLanguageTypeC;
228 break;
229 case eLanguageTypeC_plus_plus:
230 case eLanguageTypeC_plus_plus_03:
231 case eLanguageTypeC_plus_plus_11:
232 case eLanguageTypeC_plus_plus_14:
233 m_exception_language = eLanguageTypeC_plus_plus;
234 break;
235 case eLanguageTypeObjC:
236 m_exception_language = eLanguageTypeObjC;
237 break;
238 case eLanguageTypeObjC_plus_plus:
239 error.SetErrorStringWithFormat(
240 "Set exception breakpoints separately for c++ and objective-c");
241 break;
242 case eLanguageTypeUnknown:
243 error.SetErrorStringWithFormat(
244 "Unknown language type: '%s' for exception breakpoint",
245 option_arg);
246 break;
247 default:
248 error.SetErrorStringWithFormat(
249 "Unsupported language type: '%s' for exception breakpoint",
250 option_arg);
251 }
252 } break;
253
254 case 'f':
255 m_filenames.AppendIfUnique(FileSpec(option_arg, false));
256 break;
257
258 case 'F':
259 m_func_names.push_back(option_arg);
260 m_func_name_type_mask |= eFunctionNameTypeFull;
261 break;
262
263 case 'h': {
264 bool success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000265 m_catch_bp = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 if (!success)
267 error.SetErrorStringWithFormat(
268 "Invalid boolean value for on-catch option: '%s'", option_arg);
269 } break;
270
271 case 'H':
272 m_hardware = true;
273 break;
274
275 case 'i':
276 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
277 if (m_ignore_count == UINT32_MAX)
278 error.SetErrorStringWithFormat("invalid ignore count '%s'",
279 option_arg);
280 break;
281
282 case 'K': {
283 bool success;
284 bool value;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000285 value = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286 if (value)
287 m_skip_prologue = eLazyBoolYes;
288 else
289 m_skip_prologue = eLazyBoolNo;
290
291 if (!success)
292 error.SetErrorStringWithFormat(
293 "Invalid boolean value for skip prologue option: '%s'",
294 option_arg);
295 } break;
296
297 case 'l': {
298 bool success;
299 m_line_num = StringConvert::ToUInt32(option_arg, 0, 0, &success);
300 if (!success)
301 error.SetErrorStringWithFormat("invalid line number: %s.",
302 option_arg);
303 break;
304 }
305
306 case 'L':
307 m_language = Language::GetLanguageTypeFromString(option_arg);
308 if (m_language == eLanguageTypeUnknown)
309 error.SetErrorStringWithFormat(
310 "Unknown language type: '%s' for breakpoint", option_arg);
311 break;
312
313 case 'm': {
314 bool success;
315 bool value;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000316 value = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000317 if (value)
318 m_move_to_nearest_code = eLazyBoolYes;
319 else
320 m_move_to_nearest_code = eLazyBoolNo;
321
322 if (!success)
323 error.SetErrorStringWithFormat(
324 "Invalid boolean value for move-to-nearest-code option: '%s'",
325 option_arg);
326 break;
327 }
328
329 case 'M':
330 m_func_names.push_back(option_arg);
331 m_func_name_type_mask |= eFunctionNameTypeMethod;
332 break;
333
334 case 'n':
335 m_func_names.push_back(option_arg);
336 m_func_name_type_mask |= eFunctionNameTypeAuto;
337 break;
338
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000339 case 'N': {
340 if (BreakpointID::StringIsBreakpointName(option_strref, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000341 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000342 else
343 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
344 option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000345 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000346 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347
348 case 'R': {
349 lldb::addr_t tmp_offset_addr;
350 tmp_offset_addr =
351 Args::StringToAddress(execution_context, option_arg, 0, &error);
352 if (error.Success())
353 m_offset_addr = tmp_offset_addr;
354 } break;
355
356 case 'o':
357 m_one_shot = true;
358 break;
359
360 case 'O':
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000361 m_exception_extra_args.AppendArgument(llvm::StringRef("-O"));
362 m_exception_extra_args.AppendArgument(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363 break;
364
365 case 'p':
366 m_source_text_regexp.assign(option_arg);
367 break;
368
369 case 'q':
370 m_queue_name.assign(option_arg);
371 break;
372
373 case 'r':
374 m_func_regexp.assign(option_arg);
375 break;
376
377 case 's':
378 m_modules.AppendIfUnique(FileSpec(option_arg, false));
379 break;
380
381 case 'S':
382 m_func_names.push_back(option_arg);
383 m_func_name_type_mask |= eFunctionNameTypeSelector;
384 break;
385
386 case 't':
387 m_thread_id =
388 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
389 if (m_thread_id == LLDB_INVALID_THREAD_ID)
390 error.SetErrorStringWithFormat("invalid thread id string '%s'",
391 option_arg);
392 break;
393
394 case 'T':
395 m_thread_name.assign(option_arg);
396 break;
397
398 case 'w': {
399 bool success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000400 m_throw_bp = Args::StringToBoolean(option_strref, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401 if (!success)
402 error.SetErrorStringWithFormat(
403 "Invalid boolean value for on-throw option: '%s'", option_arg);
404 } break;
405
406 case 'x':
407 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
408 if (m_thread_id == UINT32_MAX)
409 error.SetErrorStringWithFormat("invalid thread index string '%s'",
410 option_arg);
411 break;
412
413 case 'X':
414 m_source_regex_func_names.insert(option_arg);
415 break;
416
417 default:
418 error.SetErrorStringWithFormat("unrecognized option '%c'",
419 short_option);
420 break;
421 }
422
423 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000424 }
425
Kate Stoneb9c1b512016-09-06 20:57:50 +0000426 void OptionParsingStarting(ExecutionContext *execution_context) override {
427 m_condition.clear();
428 m_filenames.Clear();
429 m_line_num = 0;
430 m_column = 0;
431 m_func_names.clear();
432 m_func_name_type_mask = eFunctionNameTypeNone;
433 m_func_regexp.clear();
434 m_source_text_regexp.clear();
435 m_modules.Clear();
436 m_load_addr = LLDB_INVALID_ADDRESS;
437 m_offset_addr = 0;
438 m_ignore_count = 0;
439 m_thread_id = LLDB_INVALID_THREAD_ID;
440 m_thread_index = UINT32_MAX;
441 m_thread_name.clear();
442 m_queue_name.clear();
443 m_catch_bp = false;
444 m_throw_bp = true;
445 m_hardware = false;
446 m_exception_language = eLanguageTypeUnknown;
447 m_language = lldb::eLanguageTypeUnknown;
448 m_skip_prologue = eLazyBoolCalculate;
449 m_one_shot = false;
450 m_use_dummy = false;
451 m_breakpoint_names.clear();
452 m_all_files = false;
453 m_exception_extra_args.Clear();
454 m_move_to_nearest_code = eLazyBoolCalculate;
455 m_source_regex_func_names.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000456 }
457
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000458 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000459 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000460 }
Jim Ingham5a988412012-06-08 21:56:10 +0000461
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000463
Kate Stoneb9c1b512016-09-06 20:57:50 +0000464 std::string m_condition;
465 FileSpecList m_filenames;
466 uint32_t m_line_num;
467 uint32_t m_column;
468 std::vector<std::string> m_func_names;
469 std::vector<std::string> m_breakpoint_names;
470 uint32_t m_func_name_type_mask;
471 std::string m_func_regexp;
472 std::string m_source_text_regexp;
473 FileSpecList m_modules;
474 lldb::addr_t m_load_addr;
475 lldb::addr_t m_offset_addr;
476 uint32_t m_ignore_count;
477 lldb::tid_t m_thread_id;
478 uint32_t m_thread_index;
479 std::string m_thread_name;
480 std::string m_queue_name;
481 bool m_catch_bp;
482 bool m_throw_bp;
483 bool m_hardware; // Request to use hardware breakpoints
484 lldb::LanguageType m_exception_language;
485 lldb::LanguageType m_language;
486 LazyBool m_skip_prologue;
487 bool m_one_shot;
488 bool m_use_dummy;
489 bool m_all_files;
490 Args m_exception_extra_args;
491 LazyBool m_move_to_nearest_code;
492 std::unordered_set<std::string> m_source_regex_func_names;
493 };
Jim Ingham5a988412012-06-08 21:56:10 +0000494
495protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000496 bool DoExecute(Args &command, CommandReturnObject &result) override {
497 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000498
Kate Stoneb9c1b512016-09-06 20:57:50 +0000499 if (target == nullptr) {
500 result.AppendError("Invalid target. Must set target before setting "
501 "breakpoints (see 'target create' command).");
502 result.SetStatus(eReturnStatusFailed);
503 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000504 }
505
Kate Stoneb9c1b512016-09-06 20:57:50 +0000506 // The following are the various types of breakpoints that could be set:
507 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
508 // 2). -a [-s -g] (setting breakpoint by address)
509 // 3). -n [-s -g] (setting breakpoint by function name)
510 // 4). -r [-s -g] (setting breakpoint by function name regular
511 // expression)
512 // 5). -p -f (setting a breakpoint by comparing a reg-exp
513 // to source text)
514 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
515 // given language.)
516
517 BreakpointSetType break_type = eSetTypeInvalid;
518
519 if (m_options.m_line_num != 0)
520 break_type = eSetTypeFileAndLine;
521 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
522 break_type = eSetTypeAddress;
523 else if (!m_options.m_func_names.empty())
524 break_type = eSetTypeFunctionName;
525 else if (!m_options.m_func_regexp.empty())
526 break_type = eSetTypeFunctionRegexp;
527 else if (!m_options.m_source_text_regexp.empty())
528 break_type = eSetTypeSourceRegexp;
529 else if (m_options.m_exception_language != eLanguageTypeUnknown)
530 break_type = eSetTypeException;
531
532 Breakpoint *bp = nullptr;
533 FileSpec module_spec;
534 const bool internal = false;
535
536 // If the user didn't specify skip-prologue, having an offset should turn
537 // that off.
538 if (m_options.m_offset_addr != 0 &&
539 m_options.m_skip_prologue == eLazyBoolCalculate)
540 m_options.m_skip_prologue = eLazyBoolNo;
541
542 switch (break_type) {
543 case eSetTypeFileAndLine: // Breakpoint by source position
544 {
545 FileSpec file;
546 const size_t num_files = m_options.m_filenames.GetSize();
547 if (num_files == 0) {
548 if (!GetDefaultFile(target, file, result)) {
549 result.AppendError("No file supplied and no default file available.");
550 result.SetStatus(eReturnStatusFailed);
551 return false;
552 }
553 } else if (num_files > 1) {
554 result.AppendError("Only one file at a time is allowed for file and "
555 "line breakpoints.");
556 result.SetStatus(eReturnStatusFailed);
557 return false;
558 } else
559 file = m_options.m_filenames.GetFileSpecAtIndex(0);
560
561 // Only check for inline functions if
562 LazyBool check_inlines = eLazyBoolCalculate;
563
564 bp = target
565 ->CreateBreakpoint(&(m_options.m_modules), file,
566 m_options.m_line_num, m_options.m_offset_addr,
567 check_inlines, m_options.m_skip_prologue,
568 internal, m_options.m_hardware,
569 m_options.m_move_to_nearest_code)
570 .get();
571 } break;
572
573 case eSetTypeAddress: // Breakpoint by address
574 {
575 // If a shared library has been specified, make an lldb_private::Address
576 // with the library, and
577 // use that. That way the address breakpoint will track the load location
578 // of the library.
579 size_t num_modules_specified = m_options.m_modules.GetSize();
580 if (num_modules_specified == 1) {
581 const FileSpec *file_spec =
582 m_options.m_modules.GetFileSpecPointerAtIndex(0);
583 bp = target
584 ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
585 internal, file_spec,
586 m_options.m_hardware)
587 .get();
588 } else if (num_modules_specified == 0) {
589 bp = target
590 ->CreateBreakpoint(m_options.m_load_addr, internal,
591 m_options.m_hardware)
592 .get();
593 } else {
594 result.AppendError("Only one shared library can be specified for "
595 "address breakpoints.");
596 result.SetStatus(eReturnStatusFailed);
597 return false;
598 }
599 break;
600 }
601 case eSetTypeFunctionName: // Breakpoint by function name
602 {
603 uint32_t name_type_mask = m_options.m_func_name_type_mask;
604
605 if (name_type_mask == 0)
606 name_type_mask = eFunctionNameTypeAuto;
607
608 bp = target
609 ->CreateBreakpoint(
610 &(m_options.m_modules), &(m_options.m_filenames),
611 m_options.m_func_names, name_type_mask, m_options.m_language,
612 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
613 m_options.m_hardware)
614 .get();
615 } break;
616
617 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
618 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000619 {
Zachary Turner95eae422016-09-21 16:01:28 +0000620 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000621 if (!regexp.IsValid()) {
622 char err_str[1024];
623 regexp.GetErrorAsCString(err_str, sizeof(err_str));
624 result.AppendErrorWithFormat(
625 "Function name regular expression could not be compiled: \"%s\"",
626 err_str);
627 result.SetStatus(eReturnStatusFailed);
628 return false;
629 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000630
Jim Inghame14dc262016-09-12 23:10:56 +0000631 bp = target
632 ->CreateFuncRegexBreakpoint(
633 &(m_options.m_modules), &(m_options.m_filenames), regexp,
634 m_options.m_language, m_options.m_skip_prologue, internal,
635 m_options.m_hardware)
636 .get();
637 }
638 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000639 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
640 {
641 const size_t num_files = m_options.m_filenames.GetSize();
642
643 if (num_files == 0 && !m_options.m_all_files) {
644 FileSpec file;
645 if (!GetDefaultFile(target, file, result)) {
646 result.AppendError(
647 "No files provided and could not find default file.");
648 result.SetStatus(eReturnStatusFailed);
649 return false;
650 } else {
651 m_options.m_filenames.Append(file);
652 }
653 }
654
Zachary Turner95eae422016-09-21 16:01:28 +0000655 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 if (!regexp.IsValid()) {
657 char err_str[1024];
658 regexp.GetErrorAsCString(err_str, sizeof(err_str));
659 result.AppendErrorWithFormat(
660 "Source text regular expression could not be compiled: \"%s\"",
661 err_str);
662 result.SetStatus(eReturnStatusFailed);
663 return false;
664 }
665 bp = target
666 ->CreateSourceRegexBreakpoint(
667 &(m_options.m_modules), &(m_options.m_filenames),
668 m_options.m_source_regex_func_names, regexp, internal,
669 m_options.m_hardware, m_options.m_move_to_nearest_code)
670 .get();
671 } break;
672 case eSetTypeException: {
673 Error precond_error;
674 bp = target
675 ->CreateExceptionBreakpoint(
676 m_options.m_exception_language, m_options.m_catch_bp,
677 m_options.m_throw_bp, internal,
678 &m_options.m_exception_extra_args, &precond_error)
679 .get();
680 if (precond_error.Fail()) {
681 result.AppendErrorWithFormat(
682 "Error setting extra exception arguments: %s",
683 precond_error.AsCString());
684 target->RemoveBreakpointByID(bp->GetID());
685 result.SetStatus(eReturnStatusFailed);
686 return false;
687 }
688 } break;
689 default:
690 break;
691 }
692
693 // Now set the various options that were passed in:
694 if (bp) {
695 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
696 bp->SetThreadID(m_options.m_thread_id);
697
698 if (m_options.m_thread_index != UINT32_MAX)
699 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
700
701 if (!m_options.m_thread_name.empty())
702 bp->GetOptions()->GetThreadSpec()->SetName(
703 m_options.m_thread_name.c_str());
704
705 if (!m_options.m_queue_name.empty())
706 bp->GetOptions()->GetThreadSpec()->SetQueueName(
707 m_options.m_queue_name.c_str());
708
709 if (m_options.m_ignore_count != 0)
710 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
711
712 if (!m_options.m_condition.empty())
713 bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
714
715 if (!m_options.m_breakpoint_names.empty()) {
Jim Inghamff9a91e2016-09-21 01:21:19 +0000716 Error name_error;
717 for (auto name : m_options.m_breakpoint_names) {
718 bp->AddName(name.c_str(), name_error);
719 if (name_error.Fail()) {
720 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
721 name.c_str());
722 target->RemoveBreakpointByID(bp->GetID());
723 result.SetStatus(eReturnStatusFailed);
724 return false;
725 }
726 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000727 }
728
729 bp->SetOneShot(m_options.m_one_shot);
730 }
731
732 if (bp) {
733 Stream &output_stream = result.GetOutputStream();
734 const bool show_locations = false;
735 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
736 show_locations);
737 if (target == m_interpreter.GetDebugger().GetDummyTarget())
738 output_stream.Printf("Breakpoint set in dummy target, will get copied "
739 "into future targets.\n");
740 else {
741 // Don't print out this warning for exception breakpoints. They can get
742 // set before the target
743 // is set, but we won't know how to actually set the breakpoint till we
744 // run.
745 if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) {
746 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
747 "actual locations.\n");
748 }
749 }
750 result.SetStatus(eReturnStatusSuccessFinishResult);
751 } else if (!bp) {
752 result.AppendError("Breakpoint creation failed: No breakpoint created.");
753 result.SetStatus(eReturnStatusFailed);
754 }
755
756 return result.Succeeded();
757 }
758
Jim Ingham5a988412012-06-08 21:56:10 +0000759private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000760 bool GetDefaultFile(Target *target, FileSpec &file,
761 CommandReturnObject &result) {
762 uint32_t default_line;
763 // First use the Source Manager's default file.
764 // Then use the current stack frame's file.
765 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
766 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
767 if (cur_frame == nullptr) {
768 result.AppendError(
769 "No selected frame to use to find the default file.");
770 result.SetStatus(eReturnStatusFailed);
771 return false;
772 } else if (!cur_frame->HasDebugInformation()) {
773 result.AppendError("Cannot use the selected frame to find the default "
774 "file, it has no debug info.");
775 result.SetStatus(eReturnStatusFailed);
776 return false;
777 } else {
778 const SymbolContext &sc =
779 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
780 if (sc.line_entry.file) {
781 file = sc.line_entry.file;
782 } else {
783 result.AppendError("Can't find the file for the selected frame to "
784 "use as the default file.");
785 result.SetStatus(eReturnStatusFailed);
786 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000787 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000788 }
Jim Ingham5a988412012-06-08 21:56:10 +0000789 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000790 return true;
791 }
792
793 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000794};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000795
Jim Ingham5a988412012-06-08 21:56:10 +0000796//-------------------------------------------------------------------------
797// CommandObjectBreakpointModify
798//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000799
800#pragma mark Modify::CommandOptions
801static OptionDefinition g_breakpoint_modify_options[] = {
802 // clang-format off
803 { 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." },
804 { 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." },
805 { 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." },
806 { 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." },
807 { 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." },
808 { 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." },
809 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
810 { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." },
811 { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." },
812 { 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." },
813 // clang-format on
814};
815
Jim Ingham5a988412012-06-08 21:56:10 +0000816#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000817
Kate Stoneb9c1b512016-09-06 20:57:50 +0000818class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000819public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000820 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
821 : CommandObjectParsed(interpreter, "breakpoint modify",
822 "Modify the options on a breakpoint or set of "
823 "breakpoints in the executable. "
824 "If no breakpoint is specified, acts on the last "
825 "created breakpoint. "
826 "With the exception of -e, -d and -i, passing an "
827 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000828 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000829 m_options() {
830 CommandArgumentEntry arg;
831 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
832 eArgTypeBreakpointIDRange);
833 // Add the entry for the first argument for this command to the object's
834 // arguments vector.
835 m_arguments.push_back(arg);
836 }
837
838 ~CommandObjectBreakpointModify() override = default;
839
840 Options *GetOptions() override { return &m_options; }
841
842 class CommandOptions : public Options {
843 public:
844 CommandOptions()
845 : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
846 m_thread_id_passed(false), m_thread_index(UINT32_MAX),
847 m_thread_index_passed(false), m_thread_name(), m_queue_name(),
848 m_condition(), m_one_shot(false), m_enable_passed(false),
849 m_enable_value(false), m_name_passed(false), m_queue_passed(false),
850 m_condition_passed(false), m_one_shot_passed(false),
851 m_use_dummy(false) {}
852
853 ~CommandOptions() override = default;
854
855 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
856 ExecutionContext *execution_context) override {
857 Error error;
858 const int short_option = m_getopt_table[option_idx].val;
859
860 switch (short_option) {
861 case 'c':
862 if (option_arg != nullptr)
863 m_condition.assign(option_arg);
864 else
865 m_condition.clear();
866 m_condition_passed = true;
867 break;
868 case 'd':
869 m_enable_passed = true;
870 m_enable_value = false;
871 break;
872 case 'D':
873 m_use_dummy = true;
874 break;
875 case 'e':
876 m_enable_passed = true;
877 m_enable_value = true;
878 break;
879 case 'i':
880 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
881 if (m_ignore_count == UINT32_MAX)
882 error.SetErrorStringWithFormat("invalid ignore count '%s'",
883 option_arg);
884 break;
885 case 'o': {
886 bool value, success;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000887 value = Args::StringToBoolean(
888 llvm::StringRef::withNullAsEmpty(option_arg), false, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000889 if (success) {
890 m_one_shot_passed = true;
891 m_one_shot = value;
892 } else
893 error.SetErrorStringWithFormat(
894 "invalid boolean value '%s' passed for -o option", option_arg);
895 } break;
896 case 't':
897 if (option_arg[0] == '\0') {
898 m_thread_id = LLDB_INVALID_THREAD_ID;
899 m_thread_id_passed = true;
900 } else {
901 m_thread_id =
902 StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0);
903 if (m_thread_id == LLDB_INVALID_THREAD_ID)
904 error.SetErrorStringWithFormat("invalid thread id string '%s'",
905 option_arg);
906 else
907 m_thread_id_passed = true;
908 }
909 break;
910 case 'T':
911 if (option_arg != nullptr)
912 m_thread_name.assign(option_arg);
913 else
914 m_thread_name.clear();
915 m_name_passed = true;
916 break;
917 case 'q':
918 if (option_arg != nullptr)
919 m_queue_name.assign(option_arg);
920 else
921 m_queue_name.clear();
922 m_queue_passed = true;
923 break;
924 case 'x':
925 if (option_arg[0] == '\n') {
926 m_thread_index = UINT32_MAX;
927 m_thread_index_passed = true;
928 } else {
929 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
930 if (m_thread_id == UINT32_MAX)
931 error.SetErrorStringWithFormat("invalid thread index string '%s'",
932 option_arg);
933 else
934 m_thread_index_passed = true;
935 }
936 break;
937 default:
938 error.SetErrorStringWithFormat("unrecognized option '%c'",
939 short_option);
940 break;
941 }
942
943 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000944 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000945
Kate Stoneb9c1b512016-09-06 20:57:50 +0000946 void OptionParsingStarting(ExecutionContext *execution_context) override {
947 m_ignore_count = 0;
948 m_thread_id = LLDB_INVALID_THREAD_ID;
949 m_thread_id_passed = false;
950 m_thread_index = UINT32_MAX;
951 m_thread_index_passed = false;
952 m_thread_name.clear();
953 m_queue_name.clear();
954 m_condition.clear();
955 m_one_shot = false;
956 m_enable_passed = false;
957 m_queue_passed = false;
958 m_name_passed = false;
959 m_condition_passed = false;
960 m_one_shot_passed = false;
961 m_use_dummy = false;
Jim Ingham5a988412012-06-08 21:56:10 +0000962 }
Johnny Chen7d49c9c2012-05-25 21:10:46 +0000963
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000964 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000965 return llvm::makeArrayRef(g_breakpoint_modify_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000966 }
Greg Claytone02b8502010-10-12 04:29:14 +0000967
Kate Stoneb9c1b512016-09-06 20:57:50 +0000968 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000969
Kate Stoneb9c1b512016-09-06 20:57:50 +0000970 uint32_t m_ignore_count;
971 lldb::tid_t m_thread_id;
972 bool m_thread_id_passed;
973 uint32_t m_thread_index;
974 bool m_thread_index_passed;
975 std::string m_thread_name;
976 std::string m_queue_name;
977 std::string m_condition;
978 bool m_one_shot;
979 bool m_enable_passed;
980 bool m_enable_value;
981 bool m_name_passed;
982 bool m_queue_passed;
983 bool m_condition_passed;
984 bool m_one_shot_passed;
985 bool m_use_dummy;
986 };
Jim Ingham5a988412012-06-08 21:56:10 +0000987
988protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000989 bool DoExecute(Args &command, CommandReturnObject &result) override {
990 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
991 if (target == nullptr) {
992 result.AppendError("Invalid target. No existing target or breakpoints.");
993 result.SetStatus(eReturnStatusFailed);
994 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000995 }
996
Kate Stoneb9c1b512016-09-06 20:57:50 +0000997 std::unique_lock<std::recursive_mutex> lock;
998 target->GetBreakpointList().GetListMutex(lock);
999
1000 BreakpointIDList valid_bp_ids;
1001
1002 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1003 command, target, result, &valid_bp_ids);
1004
1005 if (result.Succeeded()) {
1006 const size_t count = valid_bp_ids.GetSize();
1007 for (size_t i = 0; i < count; ++i) {
1008 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1009
1010 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1011 Breakpoint *bp =
1012 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1013 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1014 BreakpointLocation *location =
1015 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
1016 if (location) {
1017 if (m_options.m_thread_id_passed)
1018 location->SetThreadID(m_options.m_thread_id);
1019
1020 if (m_options.m_thread_index_passed)
1021 location->SetThreadIndex(m_options.m_thread_index);
1022
1023 if (m_options.m_name_passed)
1024 location->SetThreadName(m_options.m_thread_name.c_str());
1025
1026 if (m_options.m_queue_passed)
1027 location->SetQueueName(m_options.m_queue_name.c_str());
1028
1029 if (m_options.m_ignore_count != 0)
1030 location->SetIgnoreCount(m_options.m_ignore_count);
1031
1032 if (m_options.m_enable_passed)
1033 location->SetEnabled(m_options.m_enable_value);
1034
1035 if (m_options.m_condition_passed)
1036 location->SetCondition(m_options.m_condition.c_str());
1037 }
1038 } else {
1039 if (m_options.m_thread_id_passed)
1040 bp->SetThreadID(m_options.m_thread_id);
1041
1042 if (m_options.m_thread_index_passed)
1043 bp->SetThreadIndex(m_options.m_thread_index);
1044
1045 if (m_options.m_name_passed)
1046 bp->SetThreadName(m_options.m_thread_name.c_str());
1047
1048 if (m_options.m_queue_passed)
1049 bp->SetQueueName(m_options.m_queue_name.c_str());
1050
1051 if (m_options.m_ignore_count != 0)
1052 bp->SetIgnoreCount(m_options.m_ignore_count);
1053
1054 if (m_options.m_enable_passed)
1055 bp->SetEnabled(m_options.m_enable_value);
1056
1057 if (m_options.m_condition_passed)
1058 bp->SetCondition(m_options.m_condition.c_str());
1059 }
1060 }
1061 }
1062 }
1063
1064 return result.Succeeded();
1065 }
1066
Jim Ingham5a988412012-06-08 21:56:10 +00001067private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001068 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001069};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001070
Jim Ingham5a988412012-06-08 21:56:10 +00001071//-------------------------------------------------------------------------
1072// CommandObjectBreakpointEnable
1073//-------------------------------------------------------------------------
1074#pragma mark Enable
1075
Kate Stoneb9c1b512016-09-06 20:57:50 +00001076class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001077public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001078 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1079 : CommandObjectParsed(interpreter, "enable",
1080 "Enable the specified disabled breakpoint(s). If "
1081 "no breakpoints are specified, enable all of them.",
1082 nullptr) {
1083 CommandArgumentEntry arg;
1084 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1085 eArgTypeBreakpointIDRange);
1086 // Add the entry for the first argument for this command to the object's
1087 // arguments vector.
1088 m_arguments.push_back(arg);
1089 }
Jim Ingham5a988412012-06-08 21:56:10 +00001090
Kate Stoneb9c1b512016-09-06 20:57:50 +00001091 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001092
1093protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001094 bool DoExecute(Args &command, CommandReturnObject &result) override {
1095 Target *target = GetSelectedOrDummyTarget();
1096 if (target == nullptr) {
1097 result.AppendError("Invalid target. No existing target or breakpoints.");
1098 result.SetStatus(eReturnStatusFailed);
1099 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001100 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001101
1102 std::unique_lock<std::recursive_mutex> lock;
1103 target->GetBreakpointList().GetListMutex(lock);
1104
1105 const BreakpointList &breakpoints = target->GetBreakpointList();
1106
1107 size_t num_breakpoints = breakpoints.GetSize();
1108
1109 if (num_breakpoints == 0) {
1110 result.AppendError("No breakpoints exist to be enabled.");
1111 result.SetStatus(eReturnStatusFailed);
1112 return false;
1113 }
1114
1115 if (command.GetArgumentCount() == 0) {
1116 // No breakpoint selected; enable all currently set breakpoints.
1117 target->EnableAllBreakpoints();
1118 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1119 " breakpoints)\n",
1120 (uint64_t)num_breakpoints);
1121 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1122 } else {
1123 // Particular breakpoint selected; enable that breakpoint.
1124 BreakpointIDList valid_bp_ids;
1125 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1126 command, target, result, &valid_bp_ids);
1127
1128 if (result.Succeeded()) {
1129 int enable_count = 0;
1130 int loc_count = 0;
1131 const size_t count = valid_bp_ids.GetSize();
1132 for (size_t i = 0; i < count; ++i) {
1133 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1134
1135 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1136 Breakpoint *breakpoint =
1137 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1138 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1139 BreakpointLocation *location =
1140 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1141 if (location) {
1142 location->SetEnabled(true);
1143 ++loc_count;
1144 }
1145 } else {
1146 breakpoint->SetEnabled(true);
1147 ++enable_count;
1148 }
1149 }
1150 }
1151 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1152 enable_count + loc_count);
1153 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1154 }
1155 }
1156
1157 return result.Succeeded();
1158 }
Jim Ingham5a988412012-06-08 21:56:10 +00001159};
1160
1161//-------------------------------------------------------------------------
1162// CommandObjectBreakpointDisable
1163//-------------------------------------------------------------------------
1164#pragma mark Disable
1165
Kate Stoneb9c1b512016-09-06 20:57:50 +00001166class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001167public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001168 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1169 : CommandObjectParsed(
1170 interpreter, "breakpoint disable",
1171 "Disable the specified breakpoint(s) without deleting "
1172 "them. If none are specified, disable all "
1173 "breakpoints.",
1174 nullptr) {
1175 SetHelpLong(
1176 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001177If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001178 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001179
Kate Stone7428a182016-07-14 22:03:10 +00001180)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001181 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001182regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001183 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001184
1185 (lldb) break disable 1
1186 (lldb) break enable 1.1
1187
1188execution will NOT stop at location 1.1. To achieve that, type:
1189
1190 (lldb) break disable 1.*
1191 (lldb) break enable 1.1
1192
Kate Stone7428a182016-07-14 22:03:10 +00001193)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001194 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001195the second re-enables the first location.");
1196
Kate Stoneb9c1b512016-09-06 20:57:50 +00001197 CommandArgumentEntry arg;
1198 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1199 eArgTypeBreakpointIDRange);
1200 // Add the entry for the first argument for this command to the object's
1201 // arguments vector.
1202 m_arguments.push_back(arg);
1203 }
Jim Ingham5a988412012-06-08 21:56:10 +00001204
Kate Stoneb9c1b512016-09-06 20:57:50 +00001205 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001206
1207protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001208 bool DoExecute(Args &command, CommandReturnObject &result) override {
1209 Target *target = GetSelectedOrDummyTarget();
1210 if (target == nullptr) {
1211 result.AppendError("Invalid target. No existing target or breakpoints.");
1212 result.SetStatus(eReturnStatusFailed);
1213 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001214 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001215
1216 std::unique_lock<std::recursive_mutex> lock;
1217 target->GetBreakpointList().GetListMutex(lock);
1218
1219 const BreakpointList &breakpoints = target->GetBreakpointList();
1220 size_t num_breakpoints = breakpoints.GetSize();
1221
1222 if (num_breakpoints == 0) {
1223 result.AppendError("No breakpoints exist to be disabled.");
1224 result.SetStatus(eReturnStatusFailed);
1225 return false;
1226 }
1227
1228 if (command.GetArgumentCount() == 0) {
1229 // No breakpoint selected; disable all currently set breakpoints.
1230 target->DisableAllBreakpoints();
1231 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1232 " breakpoints)\n",
1233 (uint64_t)num_breakpoints);
1234 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1235 } else {
1236 // Particular breakpoint selected; disable that breakpoint.
1237 BreakpointIDList valid_bp_ids;
1238
1239 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1240 command, target, result, &valid_bp_ids);
1241
1242 if (result.Succeeded()) {
1243 int disable_count = 0;
1244 int loc_count = 0;
1245 const size_t count = valid_bp_ids.GetSize();
1246 for (size_t i = 0; i < count; ++i) {
1247 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1248
1249 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1250 Breakpoint *breakpoint =
1251 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1252 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1253 BreakpointLocation *location =
1254 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1255 if (location) {
1256 location->SetEnabled(false);
1257 ++loc_count;
1258 }
1259 } else {
1260 breakpoint->SetEnabled(false);
1261 ++disable_count;
1262 }
1263 }
1264 }
1265 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1266 disable_count + loc_count);
1267 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1268 }
1269 }
1270
1271 return result.Succeeded();
1272 }
Jim Ingham5a988412012-06-08 21:56:10 +00001273};
1274
1275//-------------------------------------------------------------------------
1276// CommandObjectBreakpointList
1277//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001278
1279#pragma mark List::CommandOptions
1280static OptionDefinition g_breakpoint_list_options[] = {
1281 // clang-format off
1282 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1283 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
1284 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1285 // But I need to see it for now, and don't want to wait.
1286 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1287 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1288 { 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." },
1289 // clang-format on
1290};
1291
Jim Ingham5a988412012-06-08 21:56:10 +00001292#pragma mark List
1293
Kate Stoneb9c1b512016-09-06 20:57:50 +00001294class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001295public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001296 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1297 : CommandObjectParsed(
1298 interpreter, "breakpoint list",
1299 "List some or all breakpoints at configurable levels of detail.",
1300 nullptr),
1301 m_options() {
1302 CommandArgumentEntry arg;
1303 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001304
Kate Stoneb9c1b512016-09-06 20:57:50 +00001305 // Define the first (and only) variant of this arg.
1306 bp_id_arg.arg_type = eArgTypeBreakpointID;
1307 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001308
Kate Stoneb9c1b512016-09-06 20:57:50 +00001309 // There is only one variant this argument could be; put it into the
1310 // argument entry.
1311 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001312
Kate Stoneb9c1b512016-09-06 20:57:50 +00001313 // Push the data for the first argument into the m_arguments vector.
1314 m_arguments.push_back(arg);
1315 }
1316
1317 ~CommandObjectBreakpointList() override = default;
1318
1319 Options *GetOptions() override { return &m_options; }
1320
1321 class CommandOptions : public Options {
1322 public:
1323 CommandOptions()
1324 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001325 }
1326
Kate Stoneb9c1b512016-09-06 20:57:50 +00001327 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001328
Kate Stoneb9c1b512016-09-06 20:57:50 +00001329 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1330 ExecutionContext *execution_context) override {
1331 Error error;
1332 const int short_option = m_getopt_table[option_idx].val;
1333
1334 switch (short_option) {
1335 case 'b':
1336 m_level = lldb::eDescriptionLevelBrief;
1337 break;
1338 case 'D':
1339 m_use_dummy = true;
1340 break;
1341 case 'f':
1342 m_level = lldb::eDescriptionLevelFull;
1343 break;
1344 case 'v':
1345 m_level = lldb::eDescriptionLevelVerbose;
1346 break;
1347 case 'i':
1348 m_internal = true;
1349 break;
1350 default:
1351 error.SetErrorStringWithFormat("unrecognized option '%c'",
1352 short_option);
1353 break;
1354 }
1355
1356 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001357 }
Jim Ingham5a988412012-06-08 21:56:10 +00001358
Kate Stoneb9c1b512016-09-06 20:57:50 +00001359 void OptionParsingStarting(ExecutionContext *execution_context) override {
1360 m_level = lldb::eDescriptionLevelFull;
1361 m_internal = false;
1362 m_use_dummy = false;
1363 }
Jim Ingham5a988412012-06-08 21:56:10 +00001364
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001365 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001366 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001367 }
Jim Ingham5a988412012-06-08 21:56:10 +00001368
Kate Stoneb9c1b512016-09-06 20:57:50 +00001369 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001370
Kate Stoneb9c1b512016-09-06 20:57:50 +00001371 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001372
Kate Stoneb9c1b512016-09-06 20:57:50 +00001373 bool m_internal;
1374 bool m_use_dummy;
1375 };
Jim Ingham5a988412012-06-08 21:56:10 +00001376
1377protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001378 bool DoExecute(Args &command, CommandReturnObject &result) override {
1379 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001380
Kate Stoneb9c1b512016-09-06 20:57:50 +00001381 if (target == nullptr) {
1382 result.AppendError("Invalid target. No current target or breakpoints.");
1383 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1384 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001385 }
1386
Kate Stoneb9c1b512016-09-06 20:57:50 +00001387 const BreakpointList &breakpoints =
1388 target->GetBreakpointList(m_options.m_internal);
1389 std::unique_lock<std::recursive_mutex> lock;
1390 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1391
1392 size_t num_breakpoints = breakpoints.GetSize();
1393
1394 if (num_breakpoints == 0) {
1395 result.AppendMessage("No breakpoints currently set.");
1396 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1397 return true;
1398 }
1399
1400 Stream &output_stream = result.GetOutputStream();
1401
1402 if (command.GetArgumentCount() == 0) {
1403 // No breakpoint selected; show info about all currently set breakpoints.
1404 result.AppendMessage("Current breakpoints:");
1405 for (size_t i = 0; i < num_breakpoints; ++i) {
1406 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1407 AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
1408 }
1409 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1410 } else {
1411 // Particular breakpoints selected; show info about that breakpoint.
1412 BreakpointIDList valid_bp_ids;
1413 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1414 command, target, result, &valid_bp_ids);
1415
1416 if (result.Succeeded()) {
1417 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1418 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1419 Breakpoint *breakpoint =
1420 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1421 AddBreakpointDescription(&output_stream, breakpoint,
1422 m_options.m_level);
1423 }
1424 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1425 } else {
1426 result.AppendError("Invalid breakpoint ID.");
1427 result.SetStatus(eReturnStatusFailed);
1428 }
1429 }
1430
1431 return result.Succeeded();
1432 }
1433
Jim Ingham5a988412012-06-08 21:56:10 +00001434private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001435 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001436};
1437
Jim Ingham5a988412012-06-08 21:56:10 +00001438//-------------------------------------------------------------------------
1439// CommandObjectBreakpointClear
1440//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001441#pragma mark Clear::CommandOptions
1442
1443static OptionDefinition g_breakpoint_clear_options[] = {
1444 // clang-format off
1445 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1446 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
1447 // clang-format on
1448};
1449
Jim Ingham5a988412012-06-08 21:56:10 +00001450#pragma mark Clear
1451
Kate Stoneb9c1b512016-09-06 20:57:50 +00001452class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001453public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001454 typedef enum BreakpointClearType {
1455 eClearTypeInvalid,
1456 eClearTypeFileAndLine
1457 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001458
Kate Stoneb9c1b512016-09-06 20:57:50 +00001459 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1460 : CommandObjectParsed(interpreter, "breakpoint clear",
1461 "Delete or disable breakpoints matching the "
1462 "specified source file and line.",
1463 "breakpoint clear <cmd-options>"),
1464 m_options() {}
1465
1466 ~CommandObjectBreakpointClear() override = default;
1467
1468 Options *GetOptions() override { return &m_options; }
1469
1470 class CommandOptions : public Options {
1471 public:
1472 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1473
1474 ~CommandOptions() override = default;
1475
1476 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1477 ExecutionContext *execution_context) override {
1478 Error error;
1479 const int short_option = m_getopt_table[option_idx].val;
1480
1481 switch (short_option) {
1482 case 'f':
1483 m_filename.assign(option_arg);
1484 break;
1485
1486 case 'l':
1487 m_line_num = StringConvert::ToUInt32(option_arg, 0);
1488 break;
1489
1490 default:
1491 error.SetErrorStringWithFormat("unrecognized option '%c'",
1492 short_option);
1493 break;
1494 }
1495
1496 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001497 }
1498
Kate Stoneb9c1b512016-09-06 20:57:50 +00001499 void OptionParsingStarting(ExecutionContext *execution_context) override {
1500 m_filename.clear();
1501 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001502 }
1503
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001504 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001505 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001506 }
Jim Ingham5a988412012-06-08 21:56:10 +00001507
Kate Stoneb9c1b512016-09-06 20:57:50 +00001508 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001509
Kate Stoneb9c1b512016-09-06 20:57:50 +00001510 std::string m_filename;
1511 uint32_t m_line_num;
1512 };
Jim Ingham5a988412012-06-08 21:56:10 +00001513
1514protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001515 bool DoExecute(Args &command, CommandReturnObject &result) override {
1516 Target *target = GetSelectedOrDummyTarget();
1517 if (target == nullptr) {
1518 result.AppendError("Invalid target. No existing target or breakpoints.");
1519 result.SetStatus(eReturnStatusFailed);
1520 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001521 }
1522
Kate Stoneb9c1b512016-09-06 20:57:50 +00001523 // The following are the various types of breakpoints that could be cleared:
1524 // 1). -f -l (clearing breakpoint by source location)
1525
1526 BreakpointClearType break_type = eClearTypeInvalid;
1527
1528 if (m_options.m_line_num != 0)
1529 break_type = eClearTypeFileAndLine;
1530
1531 std::unique_lock<std::recursive_mutex> lock;
1532 target->GetBreakpointList().GetListMutex(lock);
1533
1534 BreakpointList &breakpoints = target->GetBreakpointList();
1535 size_t num_breakpoints = breakpoints.GetSize();
1536
1537 // Early return if there's no breakpoint at all.
1538 if (num_breakpoints == 0) {
1539 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1540 result.SetStatus(eReturnStatusFailed);
1541 return result.Succeeded();
1542 }
1543
1544 // Find matching breakpoints and delete them.
1545
1546 // First create a copy of all the IDs.
1547 std::vector<break_id_t> BreakIDs;
1548 for (size_t i = 0; i < num_breakpoints; ++i)
1549 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1550
1551 int num_cleared = 0;
1552 StreamString ss;
1553 switch (break_type) {
1554 case eClearTypeFileAndLine: // Breakpoint by source position
1555 {
1556 const ConstString filename(m_options.m_filename.c_str());
1557 BreakpointLocationCollection loc_coll;
1558
1559 for (size_t i = 0; i < num_breakpoints; ++i) {
1560 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1561
1562 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1563 // If the collection size is 0, it's a full match and we can just
1564 // remove the breakpoint.
1565 if (loc_coll.GetSize() == 0) {
1566 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1567 ss.EOL();
1568 target->RemoveBreakpointByID(bp->GetID());
1569 ++num_cleared;
1570 }
1571 }
1572 }
1573 } break;
1574
1575 default:
1576 break;
1577 }
1578
1579 if (num_cleared > 0) {
1580 Stream &output_stream = result.GetOutputStream();
1581 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1582 output_stream << ss.GetData();
1583 output_stream.EOL();
1584 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1585 } else {
1586 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1587 result.SetStatus(eReturnStatusFailed);
1588 }
1589
1590 return result.Succeeded();
1591 }
1592
Jim Ingham5a988412012-06-08 21:56:10 +00001593private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001594 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001595};
1596
Jim Ingham5a988412012-06-08 21:56:10 +00001597//-------------------------------------------------------------------------
1598// CommandObjectBreakpointDelete
1599//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001600static OptionDefinition g_breakpoint_delete_options[] = {
1601 // clang-format off
1602 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1603 { 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." },
1604 // clang-format on
1605};
1606
Jim Ingham5a988412012-06-08 21:56:10 +00001607#pragma mark Delete
1608
Kate Stoneb9c1b512016-09-06 20:57:50 +00001609class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001610public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001611 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1612 : CommandObjectParsed(interpreter, "breakpoint delete",
1613 "Delete the specified breakpoint(s). If no "
1614 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001615 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001616 m_options() {
1617 CommandArgumentEntry arg;
1618 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1619 eArgTypeBreakpointIDRange);
1620 // Add the entry for the first argument for this command to the object's
1621 // arguments vector.
1622 m_arguments.push_back(arg);
1623 }
1624
1625 ~CommandObjectBreakpointDelete() override = default;
1626
1627 Options *GetOptions() override { return &m_options; }
1628
1629 class CommandOptions : public Options {
1630 public:
1631 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1632
1633 ~CommandOptions() override = default;
1634
1635 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1636 ExecutionContext *execution_context) override {
1637 Error error;
1638 const int short_option = m_getopt_table[option_idx].val;
1639
1640 switch (short_option) {
1641 case 'f':
1642 m_force = true;
1643 break;
1644
1645 case 'D':
1646 m_use_dummy = true;
1647 break;
1648
1649 default:
1650 error.SetErrorStringWithFormat("unrecognized option '%c'",
1651 short_option);
1652 break;
1653 }
1654
1655 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001656 }
1657
Kate Stoneb9c1b512016-09-06 20:57:50 +00001658 void OptionParsingStarting(ExecutionContext *execution_context) override {
1659 m_use_dummy = false;
1660 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001661 }
1662
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001663 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001664 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001665 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001666
Kate Stoneb9c1b512016-09-06 20:57:50 +00001667 // Instance variables to hold the values for command options.
1668 bool m_use_dummy;
1669 bool m_force;
1670 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001671
Jim Ingham5a988412012-06-08 21:56:10 +00001672protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001673 bool DoExecute(Args &command, CommandReturnObject &result) override {
1674 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001675
Kate Stoneb9c1b512016-09-06 20:57:50 +00001676 if (target == nullptr) {
1677 result.AppendError("Invalid target. No existing target or breakpoints.");
1678 result.SetStatus(eReturnStatusFailed);
1679 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001680 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001681
Kate Stoneb9c1b512016-09-06 20:57:50 +00001682 std::unique_lock<std::recursive_mutex> lock;
1683 target->GetBreakpointList().GetListMutex(lock);
1684
1685 const BreakpointList &breakpoints = target->GetBreakpointList();
1686
1687 size_t num_breakpoints = breakpoints.GetSize();
1688
1689 if (num_breakpoints == 0) {
1690 result.AppendError("No breakpoints exist to be deleted.");
1691 result.SetStatus(eReturnStatusFailed);
1692 return false;
1693 }
1694
1695 if (command.GetArgumentCount() == 0) {
1696 if (!m_options.m_force &&
1697 !m_interpreter.Confirm(
1698 "About to delete all breakpoints, do you want to do that?",
1699 true)) {
1700 result.AppendMessage("Operation cancelled...");
1701 } else {
1702 target->RemoveAllBreakpoints();
1703 result.AppendMessageWithFormat(
1704 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1705 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1706 }
1707 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1708 } else {
1709 // Particular breakpoint selected; disable that breakpoint.
1710 BreakpointIDList valid_bp_ids;
1711 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1712 command, target, result, &valid_bp_ids);
1713
1714 if (result.Succeeded()) {
1715 int delete_count = 0;
1716 int disable_count = 0;
1717 const size_t count = valid_bp_ids.GetSize();
1718 for (size_t i = 0; i < count; ++i) {
1719 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1720
1721 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1722 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1723 Breakpoint *breakpoint =
1724 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1725 BreakpointLocation *location =
1726 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1727 // It makes no sense to try to delete individual locations, so we
1728 // disable them instead.
1729 if (location) {
1730 location->SetEnabled(false);
1731 ++disable_count;
1732 }
1733 } else {
1734 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1735 ++delete_count;
1736 }
1737 }
1738 }
1739 result.AppendMessageWithFormat(
1740 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1741 delete_count, disable_count);
1742 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1743 }
1744 }
1745 return result.Succeeded();
1746 }
1747
Jim Ingham33df7cd2014-12-06 01:28:03 +00001748private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001749 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001750};
1751
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001752//-------------------------------------------------------------------------
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001753// CommandObjectBreakpointName
1754//-------------------------------------------------------------------------
1755
Kate Stone7428a182016-07-14 22:03:10 +00001756static OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001757 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001758 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1759 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1760 {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 +00001761 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001762};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001763class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001764public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001765 BreakpointNameOptionGroup()
1766 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1767 }
1768
1769 ~BreakpointNameOptionGroup() override = default;
1770
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001771 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001772 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001773 }
1774
1775 Error SetOptionValue(uint32_t option_idx, const char *option_value,
1776 ExecutionContext *execution_context) override {
1777 Error error;
1778 const int short_option = g_breakpoint_name_options[option_idx].short_option;
Zachary Turner6fa7681b2016-09-17 02:00:02 +00001779 llvm::StringRef option_strref(option_value ? option_value : "");
Kate Stoneb9c1b512016-09-06 20:57:50 +00001780
1781 switch (short_option) {
1782 case 'N':
Zachary Turner6fa7681b2016-09-17 02:00:02 +00001783 if (BreakpointID::StringIsBreakpointName(option_strref, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001784 error.Success())
Zachary Turner6fa7681b2016-09-17 02:00:02 +00001785 m_name.SetValueFromString(option_strref);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001786 break;
1787
1788 case 'B':
1789 if (m_breakpoint.SetValueFromString(option_value).Fail())
1790 error.SetErrorStringWithFormat(
1791 "unrecognized value \"%s\" for breakpoint", option_value);
1792 break;
1793 case 'D':
1794 if (m_use_dummy.SetValueFromString(option_value).Fail())
1795 error.SetErrorStringWithFormat(
1796 "unrecognized value \"%s\" for use-dummy", option_value);
1797 break;
1798
1799 default:
1800 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1801 short_option);
1802 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001803 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001804 return error;
1805 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001806
Kate Stoneb9c1b512016-09-06 20:57:50 +00001807 void OptionParsingStarting(ExecutionContext *execution_context) override {
1808 m_name.Clear();
1809 m_breakpoint.Clear();
1810 m_use_dummy.Clear();
1811 m_use_dummy.SetDefaultValue(false);
1812 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001813
Kate Stoneb9c1b512016-09-06 20:57:50 +00001814 OptionValueString m_name;
1815 OptionValueUInt64 m_breakpoint;
1816 OptionValueBoolean m_use_dummy;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001817};
1818
Kate Stoneb9c1b512016-09-06 20:57:50 +00001819class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001820public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001821 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1822 : CommandObjectParsed(
1823 interpreter, "add", "Add a name to the breakpoints provided.",
1824 "breakpoint name add <command-options> <breakpoint-id-list>"),
1825 m_name_options(), m_option_group() {
1826 // Create the first variant for the first (and only) argument for this
1827 // command.
1828 CommandArgumentEntry arg1;
1829 CommandArgumentData id_arg;
1830 id_arg.arg_type = eArgTypeBreakpointID;
1831 id_arg.arg_repetition = eArgRepeatOptional;
1832 arg1.push_back(id_arg);
1833 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001834
Kate Stoneb9c1b512016-09-06 20:57:50 +00001835 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1836 m_option_group.Finalize();
1837 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001838
Kate Stoneb9c1b512016-09-06 20:57:50 +00001839 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001840
Kate Stoneb9c1b512016-09-06 20:57:50 +00001841 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001842
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001843protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001844 bool DoExecute(Args &command, CommandReturnObject &result) override {
1845 if (!m_name_options.m_name.OptionWasSet()) {
1846 result.SetError("No name option provided.");
1847 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001848 }
1849
Kate Stoneb9c1b512016-09-06 20:57:50 +00001850 Target *target =
1851 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1852
1853 if (target == nullptr) {
1854 result.AppendError("Invalid target. No existing target or breakpoints.");
1855 result.SetStatus(eReturnStatusFailed);
1856 return false;
1857 }
1858
1859 std::unique_lock<std::recursive_mutex> lock;
1860 target->GetBreakpointList().GetListMutex(lock);
1861
1862 const BreakpointList &breakpoints = target->GetBreakpointList();
1863
1864 size_t num_breakpoints = breakpoints.GetSize();
1865 if (num_breakpoints == 0) {
1866 result.SetError("No breakpoints, cannot add names.");
1867 result.SetStatus(eReturnStatusFailed);
1868 return false;
1869 }
1870
1871 // Particular breakpoint selected; disable that breakpoint.
1872 BreakpointIDList valid_bp_ids;
1873 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1874 command, target, result, &valid_bp_ids);
1875
1876 if (result.Succeeded()) {
1877 if (valid_bp_ids.GetSize() == 0) {
1878 result.SetError("No breakpoints specified, cannot add names.");
1879 result.SetStatus(eReturnStatusFailed);
1880 return false;
1881 }
1882 size_t num_valid_ids = valid_bp_ids.GetSize();
1883 for (size_t index = 0; index < num_valid_ids; index++) {
1884 lldb::break_id_t bp_id =
1885 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1886 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1887 Error error; // We don't need to check the error here, since the option
1888 // parser checked it...
1889 bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
1890 }
1891 }
1892
1893 return true;
1894 }
1895
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001896private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001897 BreakpointNameOptionGroup m_name_options;
1898 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001899};
1900
Kate Stoneb9c1b512016-09-06 20:57:50 +00001901class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001902public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001903 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1904 : CommandObjectParsed(
1905 interpreter, "delete",
1906 "Delete a name from the breakpoints provided.",
1907 "breakpoint name delete <command-options> <breakpoint-id-list>"),
1908 m_name_options(), m_option_group() {
1909 // Create the first variant for the first (and only) argument for this
1910 // command.
1911 CommandArgumentEntry arg1;
1912 CommandArgumentData id_arg;
1913 id_arg.arg_type = eArgTypeBreakpointID;
1914 id_arg.arg_repetition = eArgRepeatOptional;
1915 arg1.push_back(id_arg);
1916 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001917
Kate Stoneb9c1b512016-09-06 20:57:50 +00001918 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1919 m_option_group.Finalize();
1920 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001921
Kate Stoneb9c1b512016-09-06 20:57:50 +00001922 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001923
Kate Stoneb9c1b512016-09-06 20:57:50 +00001924 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001925
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001926protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001927 bool DoExecute(Args &command, CommandReturnObject &result) override {
1928 if (!m_name_options.m_name.OptionWasSet()) {
1929 result.SetError("No name option provided.");
1930 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001931 }
1932
Kate Stoneb9c1b512016-09-06 20:57:50 +00001933 Target *target =
1934 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1935
1936 if (target == nullptr) {
1937 result.AppendError("Invalid target. No existing target or breakpoints.");
1938 result.SetStatus(eReturnStatusFailed);
1939 return false;
1940 }
1941
1942 std::unique_lock<std::recursive_mutex> lock;
1943 target->GetBreakpointList().GetListMutex(lock);
1944
1945 const BreakpointList &breakpoints = target->GetBreakpointList();
1946
1947 size_t num_breakpoints = breakpoints.GetSize();
1948 if (num_breakpoints == 0) {
1949 result.SetError("No breakpoints, cannot delete names.");
1950 result.SetStatus(eReturnStatusFailed);
1951 return false;
1952 }
1953
1954 // Particular breakpoint selected; disable that breakpoint.
1955 BreakpointIDList valid_bp_ids;
1956 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1957 command, target, result, &valid_bp_ids);
1958
1959 if (result.Succeeded()) {
1960 if (valid_bp_ids.GetSize() == 0) {
1961 result.SetError("No breakpoints specified, cannot delete names.");
1962 result.SetStatus(eReturnStatusFailed);
1963 return false;
1964 }
1965 size_t num_valid_ids = valid_bp_ids.GetSize();
1966 for (size_t index = 0; index < num_valid_ids; index++) {
1967 lldb::break_id_t bp_id =
1968 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1969 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1970 bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
1971 }
1972 }
1973
1974 return true;
1975 }
1976
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001977private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001978 BreakpointNameOptionGroup m_name_options;
1979 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001980};
1981
Kate Stoneb9c1b512016-09-06 20:57:50 +00001982class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001983public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001984 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1985 : CommandObjectParsed(interpreter, "list",
1986 "List either the names for a breakpoint or the "
1987 "breakpoints for a given name.",
1988 "breakpoint name list <command-options>"),
1989 m_name_options(), m_option_group() {
1990 m_option_group.Append(&m_name_options);
1991 m_option_group.Finalize();
1992 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001993
Kate Stoneb9c1b512016-09-06 20:57:50 +00001994 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001995
Kate Stoneb9c1b512016-09-06 20:57:50 +00001996 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001997
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001998protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001999 bool DoExecute(Args &command, CommandReturnObject &result) override {
2000 Target *target =
2001 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002002
Kate Stoneb9c1b512016-09-06 20:57:50 +00002003 if (target == nullptr) {
2004 result.AppendError("Invalid target. No existing target or breakpoints.");
2005 result.SetStatus(eReturnStatusFailed);
2006 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002007 }
2008
Kate Stoneb9c1b512016-09-06 20:57:50 +00002009 if (m_name_options.m_name.OptionWasSet()) {
2010 const char *name = m_name_options.m_name.GetCurrentValue();
2011 std::unique_lock<std::recursive_mutex> lock;
2012 target->GetBreakpointList().GetListMutex(lock);
2013
2014 BreakpointList &breakpoints = target->GetBreakpointList();
2015 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2016 if (bp_sp->MatchesName(name)) {
2017 StreamString s;
2018 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2019 s.EOL();
2020 result.AppendMessage(s.GetData());
2021 }
2022 }
2023
2024 } else if (m_name_options.m_breakpoint.OptionWasSet()) {
2025 BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(
2026 m_name_options.m_breakpoint.GetCurrentValue());
2027 if (bp_sp) {
2028 std::vector<std::string> names;
2029 bp_sp->GetNames(names);
2030 result.AppendMessage("Names:");
2031 for (auto name : names)
2032 result.AppendMessageWithFormat(" %s\n", name.c_str());
2033 } else {
2034 result.AppendErrorWithFormat(
2035 "Could not find breakpoint %" PRId64 ".\n",
2036 m_name_options.m_breakpoint.GetCurrentValue());
2037 result.SetStatus(eReturnStatusFailed);
2038 return false;
2039 }
2040 } else {
2041 result.SetError("Must specify -N or -B option to list.");
2042 result.SetStatus(eReturnStatusFailed);
2043 return false;
2044 }
2045 return true;
2046 }
2047
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002048private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002049 BreakpointNameOptionGroup m_name_options;
2050 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002051};
2052
2053//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002054// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002055//-------------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00002056class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002057public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002058 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2059 : CommandObjectMultiword(
2060 interpreter, "name", "Commands to manage name tags for breakpoints",
2061 "breakpoint name <subcommand> [<command-options>]") {
2062 CommandObjectSP add_command_object(
2063 new CommandObjectBreakpointNameAdd(interpreter));
2064 CommandObjectSP delete_command_object(
2065 new CommandObjectBreakpointNameDelete(interpreter));
2066 CommandObjectSP list_command_object(
2067 new CommandObjectBreakpointNameList(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002068
Kate Stoneb9c1b512016-09-06 20:57:50 +00002069 LoadSubCommand("add", add_command_object);
2070 LoadSubCommand("delete", delete_command_object);
2071 LoadSubCommand("list", list_command_object);
2072 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002073
Kate Stoneb9c1b512016-09-06 20:57:50 +00002074 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002075};
2076
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002077//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002078// CommandObjectBreakpointRead
2079//-------------------------------------------------------------------------
Jim Ingham3acdf382016-09-22 22:20:28 +00002080#pragma mark Read::CommandOptions
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002081static OptionDefinition g_breakpoint_read_options[] = {
2082 // clang-format off
Jim Ingham3acdf382016-09-22 22:20:28 +00002083 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2084 {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 +00002085 // clang-format on
2086};
2087
2088#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002089
2090class CommandObjectBreakpointRead : public CommandObjectParsed {
2091public:
2092 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2093 : CommandObjectParsed(interpreter, "breakpoint read",
2094 "Read and set the breakpoints previously saved to "
2095 "a file with \"breakpoint write\". ",
2096 nullptr),
2097 m_options() {
2098 CommandArgumentEntry arg;
2099 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2100 eArgTypeBreakpointIDRange);
2101 // Add the entry for the first argument for this command to the object's
2102 // arguments vector.
2103 m_arguments.push_back(arg);
2104 }
2105
2106 ~CommandObjectBreakpointRead() override = default;
2107
2108 Options *GetOptions() override { return &m_options; }
2109
2110 class CommandOptions : public Options {
2111 public:
2112 CommandOptions() : Options() {}
2113
2114 ~CommandOptions() override = default;
2115
2116 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2117 ExecutionContext *execution_context) override {
2118 Error error;
2119 const int short_option = m_getopt_table[option_idx].val;
2120
2121 switch (short_option) {
2122 case 'f':
2123 m_filename.assign(option_arg);
2124 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002125 case 'N': {
2126 Error name_error;
2127 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2128 name_error)) {
2129 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2130 name_error.AsCString());
2131 }
2132 m_names.push_back(option_arg);
2133 break;
2134 }
Jim Inghame14dc262016-09-12 23:10:56 +00002135 default:
2136 error.SetErrorStringWithFormat("unrecognized option '%c'",
2137 short_option);
2138 break;
2139 }
2140
2141 return error;
2142 }
2143
2144 void OptionParsingStarting(ExecutionContext *execution_context) override {
2145 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002146 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002147 }
2148
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002149 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002150 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002151 }
Jim Inghame14dc262016-09-12 23:10:56 +00002152
2153 // Instance variables to hold the values for command options.
2154
2155 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002156 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002157 };
2158
2159protected:
2160 bool DoExecute(Args &command, CommandReturnObject &result) override {
2161 Target *target = GetSelectedOrDummyTarget();
2162 if (target == nullptr) {
2163 result.AppendError("Invalid target. No existing target or breakpoints.");
2164 result.SetStatus(eReturnStatusFailed);
2165 return false;
2166 }
2167
Jim Ingham3acdf382016-09-22 22:20:28 +00002168 std::unique_lock<std::recursive_mutex> lock;
2169 target->GetBreakpointList().GetListMutex(lock);
2170
Jim Inghame14dc262016-09-12 23:10:56 +00002171 FileSpec input_spec(m_options.m_filename, true);
Jim Ingham01f16662016-09-14 19:07:35 +00002172 BreakpointIDList new_bps;
Jim Ingham3acdf382016-09-22 22:20:28 +00002173 Error error = target->CreateBreakpointsFromFile(input_spec,
2174 m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002175
Jim Inghame14dc262016-09-12 23:10:56 +00002176 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002177 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002178 result.SetStatus(eReturnStatusFailed);
2179 return false;
2180 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002181
2182 Stream &output_stream = result.GetOutputStream();
2183
2184 size_t num_breakpoints = new_bps.GetSize();
2185 if (num_breakpoints == 0) {
2186 result.AppendMessage("No breakpoints added.");
2187 } else {
2188 // No breakpoint selected; show info about all currently set breakpoints.
2189 result.AppendMessage("New breakpoints:");
2190 for (size_t i = 0; i < num_breakpoints; ++i) {
2191 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2192 Breakpoint *bp = target->GetBreakpointList()
2193 .FindBreakpointByID(bp_id.GetBreakpointID())
2194 .get();
2195 if (bp)
2196 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2197 false);
2198 }
2199 }
Jim Inghame14dc262016-09-12 23:10:56 +00002200 return result.Succeeded();
2201 }
2202
2203private:
2204 CommandOptions m_options;
2205};
2206
Jim Inghame14dc262016-09-12 23:10:56 +00002207//-------------------------------------------------------------------------
2208// CommandObjectBreakpointWrite
2209//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002210#pragma mark Write::CommandOptions
2211static OptionDefinition g_breakpoint_write_options[] = {
2212 // clang-format off
Jim Ingham2d3628e2016-09-22 23:42:42 +00002213 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2214 { 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 +00002215 // clang-format on
2216};
2217
2218#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002219class CommandObjectBreakpointWrite : public CommandObjectParsed {
2220public:
2221 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2222 : CommandObjectParsed(interpreter, "breakpoint write",
2223 "Write the breakpoints listed to a file that can "
2224 "be read in with \"breakpoint read\". "
2225 "If given no arguments, writes all breakpoints.",
2226 nullptr),
2227 m_options() {
2228 CommandArgumentEntry arg;
2229 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2230 eArgTypeBreakpointIDRange);
2231 // Add the entry for the first argument for this command to the object's
2232 // arguments vector.
2233 m_arguments.push_back(arg);
2234 }
2235
2236 ~CommandObjectBreakpointWrite() override = default;
2237
2238 Options *GetOptions() override { return &m_options; }
2239
2240 class CommandOptions : public Options {
2241 public:
2242 CommandOptions() : Options() {}
2243
2244 ~CommandOptions() override = default;
2245
2246 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
2247 ExecutionContext *execution_context) override {
2248 Error error;
2249 const int short_option = m_getopt_table[option_idx].val;
2250
2251 switch (short_option) {
2252 case 'f':
2253 m_filename.assign(option_arg);
2254 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002255 case 'a':
2256 m_append = true;
2257 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002258 default:
2259 error.SetErrorStringWithFormat("unrecognized option '%c'",
2260 short_option);
2261 break;
2262 }
2263
2264 return error;
2265 }
2266
2267 void OptionParsingStarting(ExecutionContext *execution_context) override {
2268 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002269 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002270 }
2271
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002272 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002273 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002274 }
Jim Inghame14dc262016-09-12 23:10:56 +00002275
2276 // Instance variables to hold the values for command options.
2277
2278 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002279 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002280 };
2281
2282protected:
2283 bool DoExecute(Args &command, CommandReturnObject &result) override {
2284 Target *target = GetSelectedOrDummyTarget();
2285 if (target == nullptr) {
2286 result.AppendError("Invalid target. No existing target or breakpoints.");
2287 result.SetStatus(eReturnStatusFailed);
2288 return false;
2289 }
2290
Jim Inghame14dc262016-09-12 23:10:56 +00002291 std::unique_lock<std::recursive_mutex> lock;
2292 target->GetBreakpointList().GetListMutex(lock);
2293
Jim Ingham01f16662016-09-14 19:07:35 +00002294 BreakpointIDList valid_bp_ids;
2295 if (command.GetArgumentCount() > 0) {
Jim Inghame14dc262016-09-12 23:10:56 +00002296 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2297 command, target, result, &valid_bp_ids);
2298
Jim Ingham01f16662016-09-14 19:07:35 +00002299 if (!result.Succeeded()) {
2300 result.SetStatus(eReturnStatusFailed);
2301 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002302 }
2303 }
Jim Ingham01f16662016-09-14 19:07:35 +00002304 Error error = target->SerializeBreakpointsToFile(
Jim Ingham2d3628e2016-09-22 23:42:42 +00002305 FileSpec(m_options.m_filename.c_str(), true), valid_bp_ids,
2306 m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002307 if (!error.Success()) {
2308 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2309 error.AsCString());
2310 result.SetStatus(eReturnStatusFailed);
2311 }
Jim Inghame14dc262016-09-12 23:10:56 +00002312 return result.Succeeded();
2313 }
2314
2315private:
2316 CommandOptions m_options;
2317};
2318
Jim Inghame14dc262016-09-12 23:10:56 +00002319//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002320// CommandObjectMultiwordBreakpoint
2321//-------------------------------------------------------------------------
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002322#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002323
Kate Stoneb9c1b512016-09-06 20:57:50 +00002324CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2325 CommandInterpreter &interpreter)
2326 : CommandObjectMultiword(
2327 interpreter, "breakpoint",
2328 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2329 "breakpoint <subcommand> [<command-options>]") {
2330 CommandObjectSP list_command_object(
2331 new CommandObjectBreakpointList(interpreter));
2332 CommandObjectSP enable_command_object(
2333 new CommandObjectBreakpointEnable(interpreter));
2334 CommandObjectSP disable_command_object(
2335 new CommandObjectBreakpointDisable(interpreter));
2336 CommandObjectSP clear_command_object(
2337 new CommandObjectBreakpointClear(interpreter));
2338 CommandObjectSP delete_command_object(
2339 new CommandObjectBreakpointDelete(interpreter));
2340 CommandObjectSP set_command_object(
2341 new CommandObjectBreakpointSet(interpreter));
2342 CommandObjectSP command_command_object(
2343 new CommandObjectBreakpointCommand(interpreter));
2344 CommandObjectSP modify_command_object(
2345 new CommandObjectBreakpointModify(interpreter));
2346 CommandObjectSP name_command_object(
2347 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002348 CommandObjectSP write_command_object(
2349 new CommandObjectBreakpointWrite(interpreter));
2350 CommandObjectSP read_command_object(
2351 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002352
Kate Stoneb9c1b512016-09-06 20:57:50 +00002353 list_command_object->SetCommandName("breakpoint list");
2354 enable_command_object->SetCommandName("breakpoint enable");
2355 disable_command_object->SetCommandName("breakpoint disable");
2356 clear_command_object->SetCommandName("breakpoint clear");
2357 delete_command_object->SetCommandName("breakpoint delete");
2358 set_command_object->SetCommandName("breakpoint set");
2359 command_command_object->SetCommandName("breakpoint command");
2360 modify_command_object->SetCommandName("breakpoint modify");
2361 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002362 write_command_object->SetCommandName("breakpoint write");
2363 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002364
Kate Stoneb9c1b512016-09-06 20:57:50 +00002365 LoadSubCommand("list", list_command_object);
2366 LoadSubCommand("enable", enable_command_object);
2367 LoadSubCommand("disable", disable_command_object);
2368 LoadSubCommand("clear", clear_command_object);
2369 LoadSubCommand("delete", delete_command_object);
2370 LoadSubCommand("set", set_command_object);
2371 LoadSubCommand("command", command_command_object);
2372 LoadSubCommand("modify", modify_command_object);
2373 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002374 LoadSubCommand("write", write_command_object);
2375 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002376}
2377
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002378CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002379
Kate Stoneb9c1b512016-09-06 20:57:50 +00002380void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2381 bool allow_locations,
2382 CommandReturnObject &result,
2383 BreakpointIDList *valid_ids) {
2384 // args can be strings representing 1). integers (for breakpoint ids)
2385 // 2). the full breakpoint & location
2386 // canonical representation
2387 // 3). the word "to" or a hyphen,
2388 // representing a range (in which case there
2389 // had *better* be an entry both before &
2390 // after of one of the first two types.
2391 // 4). A breakpoint name
2392 // If args is empty, we will use the last created breakpoint (if there is
2393 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002394
Kate Stoneb9c1b512016-09-06 20:57:50 +00002395 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002396
Kate Stoneb9c1b512016-09-06 20:57:50 +00002397 if (args.GetArgumentCount() == 0) {
2398 if (target->GetLastCreatedBreakpoint()) {
2399 valid_ids->AddBreakpointID(BreakpointID(
2400 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2401 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2402 } else {
2403 result.AppendError(
2404 "No breakpoint specified and no last created breakpoint.");
2405 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002406 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002407 return;
2408 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002409
Kate Stoneb9c1b512016-09-06 20:57:50 +00002410 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2411 // directly from the old ARGS to
2412 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead
2413 // generate a list of strings for
2414 // all the breakpoint ids in the range, and shove all of those breakpoint id
2415 // strings into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002416
Kate Stoneb9c1b512016-09-06 20:57:50 +00002417 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2418 result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002419
Kate Stoneb9c1b512016-09-06 20:57:50 +00002420 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2421 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002422
Kate Stoneb9c1b512016-09-06 20:57:50 +00002423 valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
2424 temp_args.GetArgumentCount(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002425
Kate Stoneb9c1b512016-09-06 20:57:50 +00002426 // At this point, all of the breakpoint ids that the user passed in have been
2427 // converted to breakpoint IDs
2428 // and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002429
Kate Stoneb9c1b512016-09-06 20:57:50 +00002430 if (result.Succeeded()) {
2431 // Now that we've converted everything from args into a list of breakpoint
2432 // ids, go through our tentative list
2433 // of breakpoint id's and verify that they correspond to valid/currently set
2434 // breakpoints.
2435
2436 const size_t count = valid_ids->GetSize();
2437 for (size_t i = 0; i < count; ++i) {
2438 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2439 Breakpoint *breakpoint =
2440 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2441 if (breakpoint != nullptr) {
2442 const size_t num_locations = breakpoint->GetNumLocations();
2443 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2444 StreamString id_str;
2445 BreakpointID::GetCanonicalReference(
2446 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2447 i = valid_ids->GetSize() + 1;
2448 result.AppendErrorWithFormat(
2449 "'%s' is not a currently valid breakpoint/location id.\n",
2450 id_str.GetData());
2451 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002452 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002453 } else {
2454 i = valid_ids->GetSize() + 1;
2455 result.AppendErrorWithFormat(
2456 "'%d' is not a currently valid breakpoint ID.\n",
2457 cur_bp_id.GetBreakpointID());
2458 result.SetStatus(eReturnStatusFailed);
2459 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002460 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002461 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002462}