blob: 266864d1a1f0dc4e7e46882d9453962039c78d3b [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
11// C++ Includes
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000012#include <vector>
13
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014// Other libraries and framework includes
15// Project includes
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +000016#include "CommandObjectBreakpoint.h"
17#include "CommandObjectBreakpointCommand.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Breakpoint/Breakpoint.h"
19#include "lldb/Breakpoint/BreakpointIDList.h"
20#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000021#include "lldb/Host/OptionParser.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000022#include "lldb/Interpreter/CommandCompletions.h"
23#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/CommandReturnObject.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000025#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000026#include "lldb/Interpreter/OptionValueString.h"
27#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000028#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000029#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000030#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000031#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000032#include "lldb/Target/Thread.h"
33#include "lldb/Target/ThreadSpec.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000034#include "lldb/Utility/RegularExpression.h"
35#include "lldb/Utility/StreamString.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
Zachary Turner97206d52017-05-12 04:51:55 +0000181 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
182 ExecutionContext *execution_context) override {
183 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 const int short_option = m_getopt_table[option_idx].val;
185
186 switch (short_option) {
187 case 'a': {
188 m_load_addr = Args::StringToAddress(execution_context, option_arg,
189 LLDB_INVALID_ADDRESS, &error);
190 } break;
191
192 case 'A':
193 m_all_files = true;
194 break;
195
196 case 'b':
197 m_func_names.push_back(option_arg);
198 m_func_name_type_mask |= eFunctionNameTypeBase;
199 break;
200
Zachary Turnerfe114832016-11-12 16:56:47 +0000201 case 'C':
202 if (option_arg.getAsInteger(0, m_column))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000203 error.SetErrorStringWithFormat("invalid column number: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000204 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000205 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206
207 case 'c':
208 m_condition.assign(option_arg);
209 break;
210
211 case 'D':
212 m_use_dummy = true;
213 break;
214
215 case 'E': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000216 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000217
218 switch (language) {
219 case eLanguageTypeC89:
220 case eLanguageTypeC:
221 case eLanguageTypeC99:
222 case eLanguageTypeC11:
223 m_exception_language = eLanguageTypeC;
224 break;
225 case eLanguageTypeC_plus_plus:
226 case eLanguageTypeC_plus_plus_03:
227 case eLanguageTypeC_plus_plus_11:
228 case eLanguageTypeC_plus_plus_14:
229 m_exception_language = eLanguageTypeC_plus_plus;
230 break;
231 case eLanguageTypeObjC:
232 m_exception_language = eLanguageTypeObjC;
233 break;
234 case eLanguageTypeObjC_plus_plus:
235 error.SetErrorStringWithFormat(
236 "Set exception breakpoints separately for c++ and objective-c");
237 break;
238 case eLanguageTypeUnknown:
239 error.SetErrorStringWithFormat(
240 "Unknown language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000241 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000242 break;
243 default:
244 error.SetErrorStringWithFormat(
245 "Unsupported language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000246 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000247 }
248 } break;
249
250 case 'f':
251 m_filenames.AppendIfUnique(FileSpec(option_arg, false));
252 break;
253
254 case 'F':
255 m_func_names.push_back(option_arg);
256 m_func_name_type_mask |= eFunctionNameTypeFull;
257 break;
258
259 case 'h': {
260 bool success;
Zachary Turnerfe114832016-11-12 16:56:47 +0000261 m_catch_bp = Args::StringToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000262 if (!success)
263 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000264 "Invalid boolean value for on-catch option: '%s'",
265 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000266 } break;
267
268 case 'H':
269 m_hardware = true;
270 break;
271
272 case 'i':
Zachary Turnerfe114832016-11-12 16:56:47 +0000273 if (option_arg.getAsInteger(0, m_ignore_count))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 error.SetErrorStringWithFormat("invalid ignore count '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000275 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000276 break;
277
278 case 'K': {
279 bool success;
280 bool value;
Zachary Turnerfe114832016-11-12 16:56:47 +0000281 value = Args::StringToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 if (value)
283 m_skip_prologue = eLazyBoolYes;
284 else
285 m_skip_prologue = eLazyBoolNo;
286
287 if (!success)
288 error.SetErrorStringWithFormat(
289 "Invalid boolean value for skip prologue option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000290 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 } break;
292
Zachary Turnerfe114832016-11-12 16:56:47 +0000293 case 'l':
294 if (option_arg.getAsInteger(0, m_line_num))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 error.SetErrorStringWithFormat("invalid line number: %s.",
Zachary Turnerfe114832016-11-12 16:56:47 +0000296 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000297 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000298
299 case 'L':
Zachary Turnerfe114832016-11-12 16:56:47 +0000300 m_language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000301 if (m_language == eLanguageTypeUnknown)
302 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000303 "Unknown language type: '%s' for breakpoint",
304 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305 break;
306
307 case 'm': {
308 bool success;
309 bool value;
Zachary Turnerfe114832016-11-12 16:56:47 +0000310 value = Args::StringToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000311 if (value)
312 m_move_to_nearest_code = eLazyBoolYes;
313 else
314 m_move_to_nearest_code = eLazyBoolNo;
315
316 if (!success)
317 error.SetErrorStringWithFormat(
318 "Invalid boolean value for move-to-nearest-code option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000319 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000320 break;
321 }
322
323 case 'M':
324 m_func_names.push_back(option_arg);
325 m_func_name_type_mask |= eFunctionNameTypeMethod;
326 break;
327
328 case 'n':
329 m_func_names.push_back(option_arg);
330 m_func_name_type_mask |= eFunctionNameTypeAuto;
331 break;
332
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000333 case 'N': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000334 if (BreakpointID::StringIsBreakpointName(option_arg, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000335 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000336 else
337 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000338 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000339 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000340 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000341
342 case 'R': {
343 lldb::addr_t tmp_offset_addr;
344 tmp_offset_addr =
345 Args::StringToAddress(execution_context, option_arg, 0, &error);
346 if (error.Success())
347 m_offset_addr = tmp_offset_addr;
348 } break;
349
350 case 'o':
351 m_one_shot = true;
352 break;
353
354 case 'O':
Zachary Turnerfe114832016-11-12 16:56:47 +0000355 m_exception_extra_args.AppendArgument("-O");
356 m_exception_extra_args.AppendArgument(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357 break;
358
359 case 'p':
360 m_source_text_regexp.assign(option_arg);
361 break;
362
363 case 'q':
364 m_queue_name.assign(option_arg);
365 break;
366
367 case 'r':
368 m_func_regexp.assign(option_arg);
369 break;
370
371 case 's':
372 m_modules.AppendIfUnique(FileSpec(option_arg, false));
373 break;
374
375 case 'S':
376 m_func_names.push_back(option_arg);
377 m_func_name_type_mask |= eFunctionNameTypeSelector;
378 break;
379
380 case 't':
Zachary Turnerfe114832016-11-12 16:56:47 +0000381 if (option_arg.getAsInteger(0, m_thread_id))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000382 error.SetErrorStringWithFormat("invalid thread id string '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000383 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384 break;
385
386 case 'T':
387 m_thread_name.assign(option_arg);
388 break;
389
390 case 'w': {
391 bool success;
Zachary Turnerfe114832016-11-12 16:56:47 +0000392 m_throw_bp = Args::StringToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000393 if (!success)
394 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000395 "Invalid boolean value for on-throw option: '%s'",
396 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 } break;
398
399 case 'x':
Zachary Turnerfe114832016-11-12 16:56:47 +0000400 if (option_arg.getAsInteger(0, m_thread_index))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401 error.SetErrorStringWithFormat("invalid thread index string '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000402 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000403 break;
404
405 case 'X':
406 m_source_regex_func_names.insert(option_arg);
407 break;
408
409 default:
410 error.SetErrorStringWithFormat("unrecognized option '%c'",
411 short_option);
412 break;
413 }
414
415 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000416 }
417
Kate Stoneb9c1b512016-09-06 20:57:50 +0000418 void OptionParsingStarting(ExecutionContext *execution_context) override {
419 m_condition.clear();
420 m_filenames.Clear();
421 m_line_num = 0;
422 m_column = 0;
423 m_func_names.clear();
424 m_func_name_type_mask = eFunctionNameTypeNone;
425 m_func_regexp.clear();
426 m_source_text_regexp.clear();
427 m_modules.Clear();
428 m_load_addr = LLDB_INVALID_ADDRESS;
429 m_offset_addr = 0;
430 m_ignore_count = 0;
431 m_thread_id = LLDB_INVALID_THREAD_ID;
432 m_thread_index = UINT32_MAX;
433 m_thread_name.clear();
434 m_queue_name.clear();
435 m_catch_bp = false;
436 m_throw_bp = true;
437 m_hardware = false;
438 m_exception_language = eLanguageTypeUnknown;
439 m_language = lldb::eLanguageTypeUnknown;
440 m_skip_prologue = eLazyBoolCalculate;
441 m_one_shot = false;
442 m_use_dummy = false;
443 m_breakpoint_names.clear();
444 m_all_files = false;
445 m_exception_extra_args.Clear();
446 m_move_to_nearest_code = eLazyBoolCalculate;
447 m_source_regex_func_names.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000448 }
449
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000450 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000451 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000452 }
Jim Ingham5a988412012-06-08 21:56:10 +0000453
Kate Stoneb9c1b512016-09-06 20:57:50 +0000454 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000455
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456 std::string m_condition;
457 FileSpecList m_filenames;
458 uint32_t m_line_num;
459 uint32_t m_column;
460 std::vector<std::string> m_func_names;
461 std::vector<std::string> m_breakpoint_names;
462 uint32_t m_func_name_type_mask;
463 std::string m_func_regexp;
464 std::string m_source_text_regexp;
465 FileSpecList m_modules;
466 lldb::addr_t m_load_addr;
467 lldb::addr_t m_offset_addr;
468 uint32_t m_ignore_count;
469 lldb::tid_t m_thread_id;
470 uint32_t m_thread_index;
471 std::string m_thread_name;
472 std::string m_queue_name;
473 bool m_catch_bp;
474 bool m_throw_bp;
475 bool m_hardware; // Request to use hardware breakpoints
476 lldb::LanguageType m_exception_language;
477 lldb::LanguageType m_language;
478 LazyBool m_skip_prologue;
479 bool m_one_shot;
480 bool m_use_dummy;
481 bool m_all_files;
482 Args m_exception_extra_args;
483 LazyBool m_move_to_nearest_code;
484 std::unordered_set<std::string> m_source_regex_func_names;
485 };
Jim Ingham5a988412012-06-08 21:56:10 +0000486
487protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000488 bool DoExecute(Args &command, CommandReturnObject &result) override {
489 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000490
Kate Stoneb9c1b512016-09-06 20:57:50 +0000491 if (target == nullptr) {
492 result.AppendError("Invalid target. Must set target before setting "
493 "breakpoints (see 'target create' command).");
494 result.SetStatus(eReturnStatusFailed);
495 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000496 }
497
Kate Stoneb9c1b512016-09-06 20:57:50 +0000498 // The following are the various types of breakpoints that could be set:
499 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
500 // 2). -a [-s -g] (setting breakpoint by address)
501 // 3). -n [-s -g] (setting breakpoint by function name)
502 // 4). -r [-s -g] (setting breakpoint by function name regular
503 // expression)
504 // 5). -p -f (setting a breakpoint by comparing a reg-exp
505 // to source text)
506 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
507 // given language.)
508
509 BreakpointSetType break_type = eSetTypeInvalid;
510
511 if (m_options.m_line_num != 0)
512 break_type = eSetTypeFileAndLine;
513 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
514 break_type = eSetTypeAddress;
515 else if (!m_options.m_func_names.empty())
516 break_type = eSetTypeFunctionName;
517 else if (!m_options.m_func_regexp.empty())
518 break_type = eSetTypeFunctionRegexp;
519 else if (!m_options.m_source_text_regexp.empty())
520 break_type = eSetTypeSourceRegexp;
521 else if (m_options.m_exception_language != eLanguageTypeUnknown)
522 break_type = eSetTypeException;
523
524 Breakpoint *bp = nullptr;
525 FileSpec module_spec;
526 const bool internal = false;
527
528 // If the user didn't specify skip-prologue, having an offset should turn
529 // that off.
530 if (m_options.m_offset_addr != 0 &&
531 m_options.m_skip_prologue == eLazyBoolCalculate)
532 m_options.m_skip_prologue = eLazyBoolNo;
533
534 switch (break_type) {
535 case eSetTypeFileAndLine: // Breakpoint by source position
536 {
537 FileSpec file;
538 const size_t num_files = m_options.m_filenames.GetSize();
539 if (num_files == 0) {
540 if (!GetDefaultFile(target, file, result)) {
541 result.AppendError("No file supplied and no default file available.");
542 result.SetStatus(eReturnStatusFailed);
543 return false;
544 }
545 } else if (num_files > 1) {
546 result.AppendError("Only one file at a time is allowed for file and "
547 "line breakpoints.");
548 result.SetStatus(eReturnStatusFailed);
549 return false;
550 } else
551 file = m_options.m_filenames.GetFileSpecAtIndex(0);
552
553 // Only check for inline functions if
554 LazyBool check_inlines = eLazyBoolCalculate;
555
556 bp = target
557 ->CreateBreakpoint(&(m_options.m_modules), file,
558 m_options.m_line_num, m_options.m_offset_addr,
559 check_inlines, m_options.m_skip_prologue,
560 internal, m_options.m_hardware,
561 m_options.m_move_to_nearest_code)
562 .get();
563 } break;
564
565 case eSetTypeAddress: // Breakpoint by address
566 {
567 // If a shared library has been specified, make an lldb_private::Address
568 // with the library, and
569 // use that. That way the address breakpoint will track the load location
570 // of the library.
571 size_t num_modules_specified = m_options.m_modules.GetSize();
572 if (num_modules_specified == 1) {
573 const FileSpec *file_spec =
574 m_options.m_modules.GetFileSpecPointerAtIndex(0);
575 bp = target
576 ->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
577 internal, file_spec,
578 m_options.m_hardware)
579 .get();
580 } else if (num_modules_specified == 0) {
581 bp = target
582 ->CreateBreakpoint(m_options.m_load_addr, internal,
583 m_options.m_hardware)
584 .get();
585 } else {
586 result.AppendError("Only one shared library can be specified for "
587 "address breakpoints.");
588 result.SetStatus(eReturnStatusFailed);
589 return false;
590 }
591 break;
592 }
593 case eSetTypeFunctionName: // Breakpoint by function name
594 {
595 uint32_t name_type_mask = m_options.m_func_name_type_mask;
596
597 if (name_type_mask == 0)
598 name_type_mask = eFunctionNameTypeAuto;
599
600 bp = target
601 ->CreateBreakpoint(
602 &(m_options.m_modules), &(m_options.m_filenames),
603 m_options.m_func_names, name_type_mask, m_options.m_language,
604 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
605 m_options.m_hardware)
606 .get();
607 } break;
608
609 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
610 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000611 {
Zachary Turner95eae422016-09-21 16:01:28 +0000612 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000613 if (!regexp.IsValid()) {
614 char err_str[1024];
615 regexp.GetErrorAsCString(err_str, sizeof(err_str));
616 result.AppendErrorWithFormat(
617 "Function name regular expression could not be compiled: \"%s\"",
618 err_str);
619 result.SetStatus(eReturnStatusFailed);
620 return false;
621 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000622
Jim Inghame14dc262016-09-12 23:10:56 +0000623 bp = target
624 ->CreateFuncRegexBreakpoint(
625 &(m_options.m_modules), &(m_options.m_filenames), regexp,
626 m_options.m_language, m_options.m_skip_prologue, internal,
627 m_options.m_hardware)
628 .get();
629 }
630 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000631 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
632 {
633 const size_t num_files = m_options.m_filenames.GetSize();
634
635 if (num_files == 0 && !m_options.m_all_files) {
636 FileSpec file;
637 if (!GetDefaultFile(target, file, result)) {
638 result.AppendError(
639 "No files provided and could not find default file.");
640 result.SetStatus(eReturnStatusFailed);
641 return false;
642 } else {
643 m_options.m_filenames.Append(file);
644 }
645 }
646
Zachary Turner95eae422016-09-21 16:01:28 +0000647 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000648 if (!regexp.IsValid()) {
649 char err_str[1024];
650 regexp.GetErrorAsCString(err_str, sizeof(err_str));
651 result.AppendErrorWithFormat(
652 "Source text regular expression could not be compiled: \"%s\"",
653 err_str);
654 result.SetStatus(eReturnStatusFailed);
655 return false;
656 }
657 bp = target
658 ->CreateSourceRegexBreakpoint(
659 &(m_options.m_modules), &(m_options.m_filenames),
660 m_options.m_source_regex_func_names, regexp, internal,
661 m_options.m_hardware, m_options.m_move_to_nearest_code)
662 .get();
663 } break;
664 case eSetTypeException: {
Zachary Turner97206d52017-05-12 04:51:55 +0000665 Status precond_error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000666 bp = target
667 ->CreateExceptionBreakpoint(
668 m_options.m_exception_language, m_options.m_catch_bp,
669 m_options.m_throw_bp, internal,
670 &m_options.m_exception_extra_args, &precond_error)
671 .get();
672 if (precond_error.Fail()) {
673 result.AppendErrorWithFormat(
674 "Error setting extra exception arguments: %s",
675 precond_error.AsCString());
676 target->RemoveBreakpointByID(bp->GetID());
677 result.SetStatus(eReturnStatusFailed);
678 return false;
679 }
680 } break;
681 default:
682 break;
683 }
684
685 // Now set the various options that were passed in:
686 if (bp) {
687 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID)
688 bp->SetThreadID(m_options.m_thread_id);
689
690 if (m_options.m_thread_index != UINT32_MAX)
691 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index);
692
693 if (!m_options.m_thread_name.empty())
694 bp->GetOptions()->GetThreadSpec()->SetName(
695 m_options.m_thread_name.c_str());
696
697 if (!m_options.m_queue_name.empty())
698 bp->GetOptions()->GetThreadSpec()->SetQueueName(
699 m_options.m_queue_name.c_str());
700
701 if (m_options.m_ignore_count != 0)
702 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count);
703
704 if (!m_options.m_condition.empty())
705 bp->GetOptions()->SetCondition(m_options.m_condition.c_str());
706
707 if (!m_options.m_breakpoint_names.empty()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000708 Status name_error;
Jim Inghamff9a91e2016-09-21 01:21:19 +0000709 for (auto name : m_options.m_breakpoint_names) {
710 bp->AddName(name.c_str(), name_error);
711 if (name_error.Fail()) {
712 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
713 name.c_str());
714 target->RemoveBreakpointByID(bp->GetID());
715 result.SetStatus(eReturnStatusFailed);
716 return false;
717 }
718 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000719 }
720
721 bp->SetOneShot(m_options.m_one_shot);
722 }
723
724 if (bp) {
725 Stream &output_stream = result.GetOutputStream();
726 const bool show_locations = false;
727 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
728 show_locations);
729 if (target == m_interpreter.GetDebugger().GetDummyTarget())
730 output_stream.Printf("Breakpoint set in dummy target, will get copied "
731 "into future targets.\n");
732 else {
733 // Don't print out this warning for exception breakpoints. They can get
734 // set before the target
735 // is set, but we won't know how to actually set the breakpoint till we
736 // run.
737 if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) {
738 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
739 "actual locations.\n");
740 }
741 }
742 result.SetStatus(eReturnStatusSuccessFinishResult);
743 } else if (!bp) {
744 result.AppendError("Breakpoint creation failed: No breakpoint created.");
745 result.SetStatus(eReturnStatusFailed);
746 }
747
748 return result.Succeeded();
749 }
750
Jim Ingham5a988412012-06-08 21:56:10 +0000751private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000752 bool GetDefaultFile(Target *target, FileSpec &file,
753 CommandReturnObject &result) {
754 uint32_t default_line;
755 // First use the Source Manager's default file.
756 // Then use the current stack frame's file.
757 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
758 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
759 if (cur_frame == nullptr) {
760 result.AppendError(
761 "No selected frame to use to find the default file.");
762 result.SetStatus(eReturnStatusFailed);
763 return false;
764 } else if (!cur_frame->HasDebugInformation()) {
765 result.AppendError("Cannot use the selected frame to find the default "
766 "file, it has no debug info.");
767 result.SetStatus(eReturnStatusFailed);
768 return false;
769 } else {
770 const SymbolContext &sc =
771 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
772 if (sc.line_entry.file) {
773 file = sc.line_entry.file;
774 } else {
775 result.AppendError("Can't find the file for the selected frame to "
776 "use as the default file.");
777 result.SetStatus(eReturnStatusFailed);
778 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000779 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000780 }
Jim Ingham5a988412012-06-08 21:56:10 +0000781 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000782 return true;
783 }
784
785 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000786};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000787
Jim Ingham5a988412012-06-08 21:56:10 +0000788//-------------------------------------------------------------------------
789// CommandObjectBreakpointModify
790//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000791
792#pragma mark Modify::CommandOptions
793static OptionDefinition g_breakpoint_modify_options[] = {
794 // clang-format off
795 { 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." },
796 { 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." },
797 { 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." },
798 { 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." },
799 { 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." },
800 { 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." },
801 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." },
802 { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint." },
803 { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint." },
804 { 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." },
805 // clang-format on
806};
807
Jim Ingham5a988412012-06-08 21:56:10 +0000808#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000809
Kate Stoneb9c1b512016-09-06 20:57:50 +0000810class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000811public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000812 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
813 : CommandObjectParsed(interpreter, "breakpoint modify",
814 "Modify the options on a breakpoint or set of "
815 "breakpoints in the executable. "
816 "If no breakpoint is specified, acts on the last "
817 "created breakpoint. "
818 "With the exception of -e, -d and -i, passing an "
819 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000820 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000821 m_options() {
822 CommandArgumentEntry arg;
823 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
824 eArgTypeBreakpointIDRange);
825 // Add the entry for the first argument for this command to the object's
826 // arguments vector.
827 m_arguments.push_back(arg);
828 }
829
830 ~CommandObjectBreakpointModify() override = default;
831
832 Options *GetOptions() override { return &m_options; }
833
834 class CommandOptions : public Options {
835 public:
836 CommandOptions()
837 : Options(), m_ignore_count(0), m_thread_id(LLDB_INVALID_THREAD_ID),
838 m_thread_id_passed(false), m_thread_index(UINT32_MAX),
839 m_thread_index_passed(false), m_thread_name(), m_queue_name(),
840 m_condition(), m_one_shot(false), m_enable_passed(false),
841 m_enable_value(false), m_name_passed(false), m_queue_passed(false),
842 m_condition_passed(false), m_one_shot_passed(false),
843 m_use_dummy(false) {}
844
845 ~CommandOptions() override = default;
846
Zachary Turner97206d52017-05-12 04:51:55 +0000847 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
848 ExecutionContext *execution_context) override {
849 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000850 const int short_option = m_getopt_table[option_idx].val;
851
852 switch (short_option) {
853 case 'c':
Zachary Turnerfe114832016-11-12 16:56:47 +0000854 m_condition = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000855 m_condition_passed = true;
856 break;
857 case 'd':
858 m_enable_passed = true;
859 m_enable_value = false;
860 break;
861 case 'D':
862 m_use_dummy = true;
863 break;
864 case 'e':
865 m_enable_passed = true;
866 m_enable_value = true;
867 break;
868 case 'i':
Zachary Turnerfe114832016-11-12 16:56:47 +0000869 if (option_arg.getAsInteger(0, m_ignore_count))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000870 error.SetErrorStringWithFormat("invalid ignore count '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000871 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000872 break;
873 case 'o': {
874 bool value, success;
Zachary Turnerfe114832016-11-12 16:56:47 +0000875 value = Args::StringToBoolean(option_arg, false, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000876 if (success) {
877 m_one_shot_passed = true;
878 m_one_shot = value;
879 } else
880 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000881 "invalid boolean value '%s' passed for -o option",
882 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000883 } break;
884 case 't':
885 if (option_arg[0] == '\0') {
886 m_thread_id = LLDB_INVALID_THREAD_ID;
887 m_thread_id_passed = true;
888 } else {
Zachary Turnerfe114832016-11-12 16:56:47 +0000889 if (option_arg.getAsInteger(0, m_thread_id))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000890 error.SetErrorStringWithFormat("invalid thread id string '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000891 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000892 else
893 m_thread_id_passed = true;
894 }
895 break;
896 case 'T':
Zachary Turnerfe114832016-11-12 16:56:47 +0000897 m_thread_name = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000898 m_name_passed = true;
899 break;
900 case 'q':
Zachary Turnerfe114832016-11-12 16:56:47 +0000901 m_queue_name = option_arg;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000902 m_queue_passed = true;
903 break;
904 case 'x':
905 if (option_arg[0] == '\n') {
906 m_thread_index = UINT32_MAX;
907 m_thread_index_passed = true;
908 } else {
Zachary Turnerfe114832016-11-12 16:56:47 +0000909 if (option_arg.getAsInteger(0, m_thread_index))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000910 error.SetErrorStringWithFormat("invalid thread index string '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000911 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000912 else
913 m_thread_index_passed = true;
914 }
915 break;
916 default:
917 error.SetErrorStringWithFormat("unrecognized option '%c'",
918 short_option);
919 break;
920 }
921
922 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000923 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000924
Kate Stoneb9c1b512016-09-06 20:57:50 +0000925 void OptionParsingStarting(ExecutionContext *execution_context) override {
926 m_ignore_count = 0;
927 m_thread_id = LLDB_INVALID_THREAD_ID;
928 m_thread_id_passed = false;
929 m_thread_index = UINT32_MAX;
930 m_thread_index_passed = false;
931 m_thread_name.clear();
932 m_queue_name.clear();
933 m_condition.clear();
934 m_one_shot = false;
935 m_enable_passed = false;
936 m_queue_passed = false;
937 m_name_passed = false;
938 m_condition_passed = false;
939 m_one_shot_passed = false;
940 m_use_dummy = false;
Jim Ingham5a988412012-06-08 21:56:10 +0000941 }
Johnny Chen7d49c9c2012-05-25 21:10:46 +0000942
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000943 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000944 return llvm::makeArrayRef(g_breakpoint_modify_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000945 }
Greg Claytone02b8502010-10-12 04:29:14 +0000946
Kate Stoneb9c1b512016-09-06 20:57:50 +0000947 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000948
Kate Stoneb9c1b512016-09-06 20:57:50 +0000949 uint32_t m_ignore_count;
950 lldb::tid_t m_thread_id;
951 bool m_thread_id_passed;
952 uint32_t m_thread_index;
953 bool m_thread_index_passed;
954 std::string m_thread_name;
955 std::string m_queue_name;
956 std::string m_condition;
957 bool m_one_shot;
958 bool m_enable_passed;
959 bool m_enable_value;
960 bool m_name_passed;
961 bool m_queue_passed;
962 bool m_condition_passed;
963 bool m_one_shot_passed;
964 bool m_use_dummy;
965 };
Jim Ingham5a988412012-06-08 21:56:10 +0000966
967protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000968 bool DoExecute(Args &command, CommandReturnObject &result) override {
969 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
970 if (target == nullptr) {
971 result.AppendError("Invalid target. No existing target or breakpoints.");
972 result.SetStatus(eReturnStatusFailed);
973 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000974 }
975
Kate Stoneb9c1b512016-09-06 20:57:50 +0000976 std::unique_lock<std::recursive_mutex> lock;
977 target->GetBreakpointList().GetListMutex(lock);
978
979 BreakpointIDList valid_bp_ids;
980
981 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
982 command, target, result, &valid_bp_ids);
983
984 if (result.Succeeded()) {
985 const size_t count = valid_bp_ids.GetSize();
986 for (size_t i = 0; i < count; ++i) {
987 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
988
989 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
990 Breakpoint *bp =
991 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
992 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
993 BreakpointLocation *location =
994 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
995 if (location) {
996 if (m_options.m_thread_id_passed)
997 location->SetThreadID(m_options.m_thread_id);
998
999 if (m_options.m_thread_index_passed)
1000 location->SetThreadIndex(m_options.m_thread_index);
1001
1002 if (m_options.m_name_passed)
1003 location->SetThreadName(m_options.m_thread_name.c_str());
1004
1005 if (m_options.m_queue_passed)
1006 location->SetQueueName(m_options.m_queue_name.c_str());
1007
1008 if (m_options.m_ignore_count != 0)
1009 location->SetIgnoreCount(m_options.m_ignore_count);
1010
1011 if (m_options.m_enable_passed)
1012 location->SetEnabled(m_options.m_enable_value);
1013
1014 if (m_options.m_condition_passed)
1015 location->SetCondition(m_options.m_condition.c_str());
1016 }
1017 } else {
1018 if (m_options.m_thread_id_passed)
1019 bp->SetThreadID(m_options.m_thread_id);
1020
1021 if (m_options.m_thread_index_passed)
1022 bp->SetThreadIndex(m_options.m_thread_index);
1023
1024 if (m_options.m_name_passed)
1025 bp->SetThreadName(m_options.m_thread_name.c_str());
1026
1027 if (m_options.m_queue_passed)
1028 bp->SetQueueName(m_options.m_queue_name.c_str());
1029
1030 if (m_options.m_ignore_count != 0)
1031 bp->SetIgnoreCount(m_options.m_ignore_count);
1032
1033 if (m_options.m_enable_passed)
1034 bp->SetEnabled(m_options.m_enable_value);
1035
1036 if (m_options.m_condition_passed)
1037 bp->SetCondition(m_options.m_condition.c_str());
1038 }
1039 }
1040 }
1041 }
1042
1043 return result.Succeeded();
1044 }
1045
Jim Ingham5a988412012-06-08 21:56:10 +00001046private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001047 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001048};
Johnny Chen7d49c9c2012-05-25 21:10:46 +00001049
Jim Ingham5a988412012-06-08 21:56:10 +00001050//-------------------------------------------------------------------------
1051// CommandObjectBreakpointEnable
1052//-------------------------------------------------------------------------
1053#pragma mark Enable
1054
Kate Stoneb9c1b512016-09-06 20:57:50 +00001055class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001056public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001057 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
1058 : CommandObjectParsed(interpreter, "enable",
1059 "Enable the specified disabled breakpoint(s). If "
1060 "no breakpoints are specified, enable all of them.",
1061 nullptr) {
1062 CommandArgumentEntry arg;
1063 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1064 eArgTypeBreakpointIDRange);
1065 // Add the entry for the first argument for this command to the object's
1066 // arguments vector.
1067 m_arguments.push_back(arg);
1068 }
Jim Ingham5a988412012-06-08 21:56:10 +00001069
Kate Stoneb9c1b512016-09-06 20:57:50 +00001070 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001071
1072protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001073 bool DoExecute(Args &command, CommandReturnObject &result) override {
1074 Target *target = GetSelectedOrDummyTarget();
1075 if (target == nullptr) {
1076 result.AppendError("Invalid target. No existing target or breakpoints.");
1077 result.SetStatus(eReturnStatusFailed);
1078 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001079 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001080
1081 std::unique_lock<std::recursive_mutex> lock;
1082 target->GetBreakpointList().GetListMutex(lock);
1083
1084 const BreakpointList &breakpoints = target->GetBreakpointList();
1085
1086 size_t num_breakpoints = breakpoints.GetSize();
1087
1088 if (num_breakpoints == 0) {
1089 result.AppendError("No breakpoints exist to be enabled.");
1090 result.SetStatus(eReturnStatusFailed);
1091 return false;
1092 }
1093
Zachary Turner11eb9c62016-10-05 20:03:37 +00001094 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001095 // No breakpoint selected; enable all currently set breakpoints.
1096 target->EnableAllBreakpoints();
1097 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
1098 " breakpoints)\n",
1099 (uint64_t)num_breakpoints);
1100 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1101 } else {
1102 // Particular breakpoint selected; enable that breakpoint.
1103 BreakpointIDList valid_bp_ids;
1104 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1105 command, target, result, &valid_bp_ids);
1106
1107 if (result.Succeeded()) {
1108 int enable_count = 0;
1109 int loc_count = 0;
1110 const size_t count = valid_bp_ids.GetSize();
1111 for (size_t i = 0; i < count; ++i) {
1112 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1113
1114 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1115 Breakpoint *breakpoint =
1116 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1117 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1118 BreakpointLocation *location =
1119 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1120 if (location) {
1121 location->SetEnabled(true);
1122 ++loc_count;
1123 }
1124 } else {
1125 breakpoint->SetEnabled(true);
1126 ++enable_count;
1127 }
1128 }
1129 }
1130 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1131 enable_count + loc_count);
1132 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1133 }
1134 }
1135
1136 return result.Succeeded();
1137 }
Jim Ingham5a988412012-06-08 21:56:10 +00001138};
1139
1140//-------------------------------------------------------------------------
1141// CommandObjectBreakpointDisable
1142//-------------------------------------------------------------------------
1143#pragma mark Disable
1144
Kate Stoneb9c1b512016-09-06 20:57:50 +00001145class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001146public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001147 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1148 : CommandObjectParsed(
1149 interpreter, "breakpoint disable",
1150 "Disable the specified breakpoint(s) without deleting "
1151 "them. If none are specified, disable all "
1152 "breakpoints.",
1153 nullptr) {
1154 SetHelpLong(
1155 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001156If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001157 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001158
Kate Stone7428a182016-07-14 22:03:10 +00001159)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001160 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001161regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001162 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001163
1164 (lldb) break disable 1
1165 (lldb) break enable 1.1
1166
1167execution will NOT stop at location 1.1. To achieve that, type:
1168
1169 (lldb) break disable 1.*
1170 (lldb) break enable 1.1
1171
Kate Stone7428a182016-07-14 22:03:10 +00001172)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001173 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001174the second re-enables the first location.");
1175
Kate Stoneb9c1b512016-09-06 20:57:50 +00001176 CommandArgumentEntry arg;
1177 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1178 eArgTypeBreakpointIDRange);
1179 // Add the entry for the first argument for this command to the object's
1180 // arguments vector.
1181 m_arguments.push_back(arg);
1182 }
Jim Ingham5a988412012-06-08 21:56:10 +00001183
Kate Stoneb9c1b512016-09-06 20:57:50 +00001184 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001185
1186protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001187 bool DoExecute(Args &command, CommandReturnObject &result) override {
1188 Target *target = GetSelectedOrDummyTarget();
1189 if (target == nullptr) {
1190 result.AppendError("Invalid target. No existing target or breakpoints.");
1191 result.SetStatus(eReturnStatusFailed);
1192 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001193 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001194
1195 std::unique_lock<std::recursive_mutex> lock;
1196 target->GetBreakpointList().GetListMutex(lock);
1197
1198 const BreakpointList &breakpoints = target->GetBreakpointList();
1199 size_t num_breakpoints = breakpoints.GetSize();
1200
1201 if (num_breakpoints == 0) {
1202 result.AppendError("No breakpoints exist to be disabled.");
1203 result.SetStatus(eReturnStatusFailed);
1204 return false;
1205 }
1206
Zachary Turner11eb9c62016-10-05 20:03:37 +00001207 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001208 // No breakpoint selected; disable all currently set breakpoints.
1209 target->DisableAllBreakpoints();
1210 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1211 " breakpoints)\n",
1212 (uint64_t)num_breakpoints);
1213 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1214 } else {
1215 // Particular breakpoint selected; disable that breakpoint.
1216 BreakpointIDList valid_bp_ids;
1217
1218 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1219 command, target, result, &valid_bp_ids);
1220
1221 if (result.Succeeded()) {
1222 int disable_count = 0;
1223 int loc_count = 0;
1224 const size_t count = valid_bp_ids.GetSize();
1225 for (size_t i = 0; i < count; ++i) {
1226 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1227
1228 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1229 Breakpoint *breakpoint =
1230 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1231 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1232 BreakpointLocation *location =
1233 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1234 if (location) {
1235 location->SetEnabled(false);
1236 ++loc_count;
1237 }
1238 } else {
1239 breakpoint->SetEnabled(false);
1240 ++disable_count;
1241 }
1242 }
1243 }
1244 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1245 disable_count + loc_count);
1246 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1247 }
1248 }
1249
1250 return result.Succeeded();
1251 }
Jim Ingham5a988412012-06-08 21:56:10 +00001252};
1253
1254//-------------------------------------------------------------------------
1255// CommandObjectBreakpointList
1256//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001257
1258#pragma mark List::CommandOptions
1259static OptionDefinition g_breakpoint_list_options[] = {
1260 // clang-format off
1261 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show debugger internal breakpoints" },
1262 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a brief description of the breakpoint (no location info)." },
1263 // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
1264 // But I need to see it for now, and don't want to wait.
1265 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Give a full description of the breakpoint and its locations." },
1266 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
1267 { 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." },
1268 // clang-format on
1269};
1270
Jim Ingham5a988412012-06-08 21:56:10 +00001271#pragma mark List
1272
Kate Stoneb9c1b512016-09-06 20:57:50 +00001273class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001274public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001275 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1276 : CommandObjectParsed(
1277 interpreter, "breakpoint list",
1278 "List some or all breakpoints at configurable levels of detail.",
1279 nullptr),
1280 m_options() {
1281 CommandArgumentEntry arg;
1282 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001283
Kate Stoneb9c1b512016-09-06 20:57:50 +00001284 // Define the first (and only) variant of this arg.
1285 bp_id_arg.arg_type = eArgTypeBreakpointID;
1286 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001287
Kate Stoneb9c1b512016-09-06 20:57:50 +00001288 // There is only one variant this argument could be; put it into the
1289 // argument entry.
1290 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001291
Kate Stoneb9c1b512016-09-06 20:57:50 +00001292 // Push the data for the first argument into the m_arguments vector.
1293 m_arguments.push_back(arg);
1294 }
1295
1296 ~CommandObjectBreakpointList() override = default;
1297
1298 Options *GetOptions() override { return &m_options; }
1299
1300 class CommandOptions : public Options {
1301 public:
1302 CommandOptions()
1303 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001304 }
1305
Kate Stoneb9c1b512016-09-06 20:57:50 +00001306 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001307
Zachary Turner97206d52017-05-12 04:51:55 +00001308 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1309 ExecutionContext *execution_context) override {
1310 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001311 const int short_option = m_getopt_table[option_idx].val;
1312
1313 switch (short_option) {
1314 case 'b':
1315 m_level = lldb::eDescriptionLevelBrief;
1316 break;
1317 case 'D':
1318 m_use_dummy = true;
1319 break;
1320 case 'f':
1321 m_level = lldb::eDescriptionLevelFull;
1322 break;
1323 case 'v':
1324 m_level = lldb::eDescriptionLevelVerbose;
1325 break;
1326 case 'i':
1327 m_internal = true;
1328 break;
1329 default:
1330 error.SetErrorStringWithFormat("unrecognized option '%c'",
1331 short_option);
1332 break;
1333 }
1334
1335 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001336 }
Jim Ingham5a988412012-06-08 21:56:10 +00001337
Kate Stoneb9c1b512016-09-06 20:57:50 +00001338 void OptionParsingStarting(ExecutionContext *execution_context) override {
1339 m_level = lldb::eDescriptionLevelFull;
1340 m_internal = false;
1341 m_use_dummy = false;
1342 }
Jim Ingham5a988412012-06-08 21:56:10 +00001343
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001344 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001345 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001346 }
Jim Ingham5a988412012-06-08 21:56:10 +00001347
Kate Stoneb9c1b512016-09-06 20:57:50 +00001348 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001349
Kate Stoneb9c1b512016-09-06 20:57:50 +00001350 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001351
Kate Stoneb9c1b512016-09-06 20:57:50 +00001352 bool m_internal;
1353 bool m_use_dummy;
1354 };
Jim Ingham5a988412012-06-08 21:56:10 +00001355
1356protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001357 bool DoExecute(Args &command, CommandReturnObject &result) override {
1358 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001359
Kate Stoneb9c1b512016-09-06 20:57:50 +00001360 if (target == nullptr) {
1361 result.AppendError("Invalid target. No current target or breakpoints.");
1362 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1363 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001364 }
1365
Kate Stoneb9c1b512016-09-06 20:57:50 +00001366 const BreakpointList &breakpoints =
1367 target->GetBreakpointList(m_options.m_internal);
1368 std::unique_lock<std::recursive_mutex> lock;
1369 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1370
1371 size_t num_breakpoints = breakpoints.GetSize();
1372
1373 if (num_breakpoints == 0) {
1374 result.AppendMessage("No breakpoints currently set.");
1375 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1376 return true;
1377 }
1378
1379 Stream &output_stream = result.GetOutputStream();
1380
Zachary Turner11eb9c62016-10-05 20:03:37 +00001381 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001382 // No breakpoint selected; show info about all currently set breakpoints.
1383 result.AppendMessage("Current breakpoints:");
1384 for (size_t i = 0; i < num_breakpoints; ++i) {
1385 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1386 AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level);
1387 }
1388 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1389 } else {
1390 // Particular breakpoints selected; show info about that breakpoint.
1391 BreakpointIDList valid_bp_ids;
1392 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1393 command, target, result, &valid_bp_ids);
1394
1395 if (result.Succeeded()) {
1396 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1397 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1398 Breakpoint *breakpoint =
1399 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1400 AddBreakpointDescription(&output_stream, breakpoint,
1401 m_options.m_level);
1402 }
1403 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1404 } else {
1405 result.AppendError("Invalid breakpoint ID.");
1406 result.SetStatus(eReturnStatusFailed);
1407 }
1408 }
1409
1410 return result.Succeeded();
1411 }
1412
Jim Ingham5a988412012-06-08 21:56:10 +00001413private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001414 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001415};
1416
Jim Ingham5a988412012-06-08 21:56:10 +00001417//-------------------------------------------------------------------------
1418// CommandObjectBreakpointClear
1419//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001420#pragma mark Clear::CommandOptions
1421
1422static OptionDefinition g_breakpoint_clear_options[] = {
1423 // clang-format off
1424 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." },
1425 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." }
1426 // clang-format on
1427};
1428
Jim Ingham5a988412012-06-08 21:56:10 +00001429#pragma mark Clear
1430
Kate Stoneb9c1b512016-09-06 20:57:50 +00001431class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001432public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001433 typedef enum BreakpointClearType {
1434 eClearTypeInvalid,
1435 eClearTypeFileAndLine
1436 } BreakpointClearType;
Jim Ingham5a988412012-06-08 21:56:10 +00001437
Kate Stoneb9c1b512016-09-06 20:57:50 +00001438 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1439 : CommandObjectParsed(interpreter, "breakpoint clear",
1440 "Delete or disable breakpoints matching the "
1441 "specified source file and line.",
1442 "breakpoint clear <cmd-options>"),
1443 m_options() {}
1444
1445 ~CommandObjectBreakpointClear() override = default;
1446
1447 Options *GetOptions() override { return &m_options; }
1448
1449 class CommandOptions : public Options {
1450 public:
1451 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1452
1453 ~CommandOptions() override = default;
1454
Zachary Turner97206d52017-05-12 04:51:55 +00001455 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1456 ExecutionContext *execution_context) override {
1457 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001458 const int short_option = m_getopt_table[option_idx].val;
1459
1460 switch (short_option) {
1461 case 'f':
1462 m_filename.assign(option_arg);
1463 break;
1464
1465 case 'l':
Zachary Turnerfe114832016-11-12 16:56:47 +00001466 option_arg.getAsInteger(0, m_line_num);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001467 break;
1468
1469 default:
1470 error.SetErrorStringWithFormat("unrecognized option '%c'",
1471 short_option);
1472 break;
1473 }
1474
1475 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001476 }
1477
Kate Stoneb9c1b512016-09-06 20:57:50 +00001478 void OptionParsingStarting(ExecutionContext *execution_context) override {
1479 m_filename.clear();
1480 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001481 }
1482
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001483 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001484 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001485 }
Jim Ingham5a988412012-06-08 21:56:10 +00001486
Kate Stoneb9c1b512016-09-06 20:57:50 +00001487 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001488
Kate Stoneb9c1b512016-09-06 20:57:50 +00001489 std::string m_filename;
1490 uint32_t m_line_num;
1491 };
Jim Ingham5a988412012-06-08 21:56:10 +00001492
1493protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001494 bool DoExecute(Args &command, CommandReturnObject &result) override {
1495 Target *target = GetSelectedOrDummyTarget();
1496 if (target == nullptr) {
1497 result.AppendError("Invalid target. No existing target or breakpoints.");
1498 result.SetStatus(eReturnStatusFailed);
1499 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001500 }
1501
Kate Stoneb9c1b512016-09-06 20:57:50 +00001502 // The following are the various types of breakpoints that could be cleared:
1503 // 1). -f -l (clearing breakpoint by source location)
1504
1505 BreakpointClearType break_type = eClearTypeInvalid;
1506
1507 if (m_options.m_line_num != 0)
1508 break_type = eClearTypeFileAndLine;
1509
1510 std::unique_lock<std::recursive_mutex> lock;
1511 target->GetBreakpointList().GetListMutex(lock);
1512
1513 BreakpointList &breakpoints = target->GetBreakpointList();
1514 size_t num_breakpoints = breakpoints.GetSize();
1515
1516 // Early return if there's no breakpoint at all.
1517 if (num_breakpoints == 0) {
1518 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1519 result.SetStatus(eReturnStatusFailed);
1520 return result.Succeeded();
1521 }
1522
1523 // Find matching breakpoints and delete them.
1524
1525 // First create a copy of all the IDs.
1526 std::vector<break_id_t> BreakIDs;
1527 for (size_t i = 0; i < num_breakpoints; ++i)
1528 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1529
1530 int num_cleared = 0;
1531 StreamString ss;
1532 switch (break_type) {
1533 case eClearTypeFileAndLine: // Breakpoint by source position
1534 {
1535 const ConstString filename(m_options.m_filename.c_str());
1536 BreakpointLocationCollection loc_coll;
1537
1538 for (size_t i = 0; i < num_breakpoints; ++i) {
1539 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1540
1541 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1542 // If the collection size is 0, it's a full match and we can just
1543 // remove the breakpoint.
1544 if (loc_coll.GetSize() == 0) {
1545 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1546 ss.EOL();
1547 target->RemoveBreakpointByID(bp->GetID());
1548 ++num_cleared;
1549 }
1550 }
1551 }
1552 } break;
1553
1554 default:
1555 break;
1556 }
1557
1558 if (num_cleared > 0) {
1559 Stream &output_stream = result.GetOutputStream();
1560 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
Zachary Turnerc1564272016-11-16 21:15:24 +00001561 output_stream << ss.GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001562 output_stream.EOL();
1563 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1564 } else {
1565 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1566 result.SetStatus(eReturnStatusFailed);
1567 }
1568
1569 return result.Succeeded();
1570 }
1571
Jim Ingham5a988412012-06-08 21:56:10 +00001572private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001573 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001574};
1575
Jim Ingham5a988412012-06-08 21:56:10 +00001576//-------------------------------------------------------------------------
1577// CommandObjectBreakpointDelete
1578//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001579static OptionDefinition g_breakpoint_delete_options[] = {
1580 // clang-format off
1581 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." },
1582 { 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." },
1583 // clang-format on
1584};
1585
Jim Ingham5a988412012-06-08 21:56:10 +00001586#pragma mark Delete
1587
Kate Stoneb9c1b512016-09-06 20:57:50 +00001588class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001589public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001590 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1591 : CommandObjectParsed(interpreter, "breakpoint delete",
1592 "Delete the specified breakpoint(s). If no "
1593 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001594 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001595 m_options() {
1596 CommandArgumentEntry arg;
1597 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1598 eArgTypeBreakpointIDRange);
1599 // Add the entry for the first argument for this command to the object's
1600 // arguments vector.
1601 m_arguments.push_back(arg);
1602 }
1603
1604 ~CommandObjectBreakpointDelete() override = default;
1605
1606 Options *GetOptions() override { return &m_options; }
1607
1608 class CommandOptions : public Options {
1609 public:
1610 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1611
1612 ~CommandOptions() override = default;
1613
Zachary Turner97206d52017-05-12 04:51:55 +00001614 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1615 ExecutionContext *execution_context) override {
1616 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001617 const int short_option = m_getopt_table[option_idx].val;
1618
1619 switch (short_option) {
1620 case 'f':
1621 m_force = true;
1622 break;
1623
1624 case 'D':
1625 m_use_dummy = true;
1626 break;
1627
1628 default:
1629 error.SetErrorStringWithFormat("unrecognized option '%c'",
1630 short_option);
1631 break;
1632 }
1633
1634 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001635 }
1636
Kate Stoneb9c1b512016-09-06 20:57:50 +00001637 void OptionParsingStarting(ExecutionContext *execution_context) override {
1638 m_use_dummy = false;
1639 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001640 }
1641
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001642 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001643 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001644 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001645
Kate Stoneb9c1b512016-09-06 20:57:50 +00001646 // Instance variables to hold the values for command options.
1647 bool m_use_dummy;
1648 bool m_force;
1649 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001650
Jim Ingham5a988412012-06-08 21:56:10 +00001651protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001652 bool DoExecute(Args &command, CommandReturnObject &result) override {
1653 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001654
Kate Stoneb9c1b512016-09-06 20:57:50 +00001655 if (target == nullptr) {
1656 result.AppendError("Invalid target. No existing target or breakpoints.");
1657 result.SetStatus(eReturnStatusFailed);
1658 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001659 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001660
Kate Stoneb9c1b512016-09-06 20:57:50 +00001661 std::unique_lock<std::recursive_mutex> lock;
1662 target->GetBreakpointList().GetListMutex(lock);
1663
1664 const BreakpointList &breakpoints = target->GetBreakpointList();
1665
1666 size_t num_breakpoints = breakpoints.GetSize();
1667
1668 if (num_breakpoints == 0) {
1669 result.AppendError("No breakpoints exist to be deleted.");
1670 result.SetStatus(eReturnStatusFailed);
1671 return false;
1672 }
1673
Zachary Turner11eb9c62016-10-05 20:03:37 +00001674 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001675 if (!m_options.m_force &&
1676 !m_interpreter.Confirm(
1677 "About to delete all breakpoints, do you want to do that?",
1678 true)) {
1679 result.AppendMessage("Operation cancelled...");
1680 } else {
1681 target->RemoveAllBreakpoints();
1682 result.AppendMessageWithFormat(
1683 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1684 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1685 }
1686 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1687 } else {
1688 // Particular breakpoint selected; disable that breakpoint.
1689 BreakpointIDList valid_bp_ids;
1690 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1691 command, target, result, &valid_bp_ids);
1692
1693 if (result.Succeeded()) {
1694 int delete_count = 0;
1695 int disable_count = 0;
1696 const size_t count = valid_bp_ids.GetSize();
1697 for (size_t i = 0; i < count; ++i) {
1698 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1699
1700 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1701 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1702 Breakpoint *breakpoint =
1703 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1704 BreakpointLocation *location =
1705 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1706 // It makes no sense to try to delete individual locations, so we
1707 // disable them instead.
1708 if (location) {
1709 location->SetEnabled(false);
1710 ++disable_count;
1711 }
1712 } else {
1713 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1714 ++delete_count;
1715 }
1716 }
1717 }
1718 result.AppendMessageWithFormat(
1719 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1720 delete_count, disable_count);
1721 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1722 }
1723 }
1724 return result.Succeeded();
1725 }
1726
Jim Ingham33df7cd2014-12-06 01:28:03 +00001727private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001728 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001729};
1730
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001731//-------------------------------------------------------------------------
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001732// CommandObjectBreakpointName
1733//-------------------------------------------------------------------------
1734
Kate Stone7428a182016-07-14 22:03:10 +00001735static OptionDefinition g_breakpoint_name_options[] = {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001736 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +00001737 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."},
1738 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."},
1739 {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 +00001740 // clang-format on
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001741};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001742class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001743public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001744 BreakpointNameOptionGroup()
1745 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1746 }
1747
1748 ~BreakpointNameOptionGroup() override = default;
1749
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001750 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001751 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001752 }
1753
Zachary Turner97206d52017-05-12 04:51:55 +00001754 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1755 ExecutionContext *execution_context) override {
1756 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001757 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1758
1759 switch (short_option) {
1760 case 'N':
Zachary Turnerfe114832016-11-12 16:56:47 +00001761 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001762 error.Success())
Zachary Turnerfe114832016-11-12 16:56:47 +00001763 m_name.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001764 break;
1765
1766 case 'B':
Zachary Turnerfe114832016-11-12 16:56:47 +00001767 if (m_breakpoint.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001768 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001769 "unrecognized value \"%s\" for breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +00001770 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001771 break;
1772 case 'D':
Zachary Turnerfe114832016-11-12 16:56:47 +00001773 if (m_use_dummy.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001774 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001775 "unrecognized value \"%s\" for use-dummy",
Zachary Turnerfe114832016-11-12 16:56:47 +00001776 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001777 break;
1778
1779 default:
1780 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1781 short_option);
1782 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001783 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001784 return error;
1785 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001786
Kate Stoneb9c1b512016-09-06 20:57:50 +00001787 void OptionParsingStarting(ExecutionContext *execution_context) override {
1788 m_name.Clear();
1789 m_breakpoint.Clear();
1790 m_use_dummy.Clear();
1791 m_use_dummy.SetDefaultValue(false);
1792 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001793
Kate Stoneb9c1b512016-09-06 20:57:50 +00001794 OptionValueString m_name;
1795 OptionValueUInt64 m_breakpoint;
1796 OptionValueBoolean m_use_dummy;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001797};
1798
Kate Stoneb9c1b512016-09-06 20:57:50 +00001799class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001800public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001801 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1802 : CommandObjectParsed(
1803 interpreter, "add", "Add a name to the breakpoints provided.",
1804 "breakpoint name add <command-options> <breakpoint-id-list>"),
1805 m_name_options(), m_option_group() {
1806 // Create the first variant for the first (and only) argument for this
1807 // command.
1808 CommandArgumentEntry arg1;
1809 CommandArgumentData id_arg;
1810 id_arg.arg_type = eArgTypeBreakpointID;
1811 id_arg.arg_repetition = eArgRepeatOptional;
1812 arg1.push_back(id_arg);
1813 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001814
Kate Stoneb9c1b512016-09-06 20:57:50 +00001815 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1816 m_option_group.Finalize();
1817 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001818
Kate Stoneb9c1b512016-09-06 20:57:50 +00001819 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001820
Kate Stoneb9c1b512016-09-06 20:57:50 +00001821 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001822
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001823protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001824 bool DoExecute(Args &command, CommandReturnObject &result) override {
1825 if (!m_name_options.m_name.OptionWasSet()) {
1826 result.SetError("No name option provided.");
1827 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001828 }
1829
Kate Stoneb9c1b512016-09-06 20:57:50 +00001830 Target *target =
1831 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1832
1833 if (target == nullptr) {
1834 result.AppendError("Invalid target. No existing target or breakpoints.");
1835 result.SetStatus(eReturnStatusFailed);
1836 return false;
1837 }
1838
1839 std::unique_lock<std::recursive_mutex> lock;
1840 target->GetBreakpointList().GetListMutex(lock);
1841
1842 const BreakpointList &breakpoints = target->GetBreakpointList();
1843
1844 size_t num_breakpoints = breakpoints.GetSize();
1845 if (num_breakpoints == 0) {
1846 result.SetError("No breakpoints, cannot add names.");
1847 result.SetStatus(eReturnStatusFailed);
1848 return false;
1849 }
1850
1851 // Particular breakpoint selected; disable that breakpoint.
1852 BreakpointIDList valid_bp_ids;
1853 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1854 command, target, result, &valid_bp_ids);
1855
1856 if (result.Succeeded()) {
1857 if (valid_bp_ids.GetSize() == 0) {
1858 result.SetError("No breakpoints specified, cannot add names.");
1859 result.SetStatus(eReturnStatusFailed);
1860 return false;
1861 }
1862 size_t num_valid_ids = valid_bp_ids.GetSize();
1863 for (size_t index = 0; index < num_valid_ids; index++) {
1864 lldb::break_id_t bp_id =
1865 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1866 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Zachary Turner97206d52017-05-12 04:51:55 +00001867 Status error; // We don't need to check the error here, since the option
1868 // parser checked it...
Kate Stoneb9c1b512016-09-06 20:57:50 +00001869 bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error);
1870 }
1871 }
1872
1873 return true;
1874 }
1875
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001876private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001877 BreakpointNameOptionGroup m_name_options;
1878 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001879};
1880
Kate Stoneb9c1b512016-09-06 20:57:50 +00001881class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001882public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001883 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1884 : CommandObjectParsed(
1885 interpreter, "delete",
1886 "Delete a name from the breakpoints provided.",
1887 "breakpoint name delete <command-options> <breakpoint-id-list>"),
1888 m_name_options(), m_option_group() {
1889 // Create the first variant for the first (and only) argument for this
1890 // command.
1891 CommandArgumentEntry arg1;
1892 CommandArgumentData id_arg;
1893 id_arg.arg_type = eArgTypeBreakpointID;
1894 id_arg.arg_repetition = eArgRepeatOptional;
1895 arg1.push_back(id_arg);
1896 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001897
Kate Stoneb9c1b512016-09-06 20:57:50 +00001898 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1899 m_option_group.Finalize();
1900 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001901
Kate Stoneb9c1b512016-09-06 20:57:50 +00001902 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001903
Kate Stoneb9c1b512016-09-06 20:57:50 +00001904 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001905
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001906protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001907 bool DoExecute(Args &command, CommandReturnObject &result) override {
1908 if (!m_name_options.m_name.OptionWasSet()) {
1909 result.SetError("No name option provided.");
1910 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001911 }
1912
Kate Stoneb9c1b512016-09-06 20:57:50 +00001913 Target *target =
1914 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1915
1916 if (target == nullptr) {
1917 result.AppendError("Invalid target. No existing target or breakpoints.");
1918 result.SetStatus(eReturnStatusFailed);
1919 return false;
1920 }
1921
1922 std::unique_lock<std::recursive_mutex> lock;
1923 target->GetBreakpointList().GetListMutex(lock);
1924
1925 const BreakpointList &breakpoints = target->GetBreakpointList();
1926
1927 size_t num_breakpoints = breakpoints.GetSize();
1928 if (num_breakpoints == 0) {
1929 result.SetError("No breakpoints, cannot delete names.");
1930 result.SetStatus(eReturnStatusFailed);
1931 return false;
1932 }
1933
1934 // Particular breakpoint selected; disable that breakpoint.
1935 BreakpointIDList valid_bp_ids;
1936 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1937 command, target, result, &valid_bp_ids);
1938
1939 if (result.Succeeded()) {
1940 if (valid_bp_ids.GetSize() == 0) {
1941 result.SetError("No breakpoints specified, cannot delete names.");
1942 result.SetStatus(eReturnStatusFailed);
1943 return false;
1944 }
1945 size_t num_valid_ids = valid_bp_ids.GetSize();
1946 for (size_t index = 0; index < num_valid_ids; index++) {
1947 lldb::break_id_t bp_id =
1948 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1949 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1950 bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue());
1951 }
1952 }
1953
1954 return true;
1955 }
1956
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001957private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001958 BreakpointNameOptionGroup m_name_options;
1959 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001960};
1961
Kate Stoneb9c1b512016-09-06 20:57:50 +00001962class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001963public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001964 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1965 : CommandObjectParsed(interpreter, "list",
1966 "List either the names for a breakpoint or the "
1967 "breakpoints for a given name.",
1968 "breakpoint name list <command-options>"),
1969 m_name_options(), m_option_group() {
1970 m_option_group.Append(&m_name_options);
1971 m_option_group.Finalize();
1972 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001973
Kate Stoneb9c1b512016-09-06 20:57:50 +00001974 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001975
Kate Stoneb9c1b512016-09-06 20:57:50 +00001976 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001977
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001978protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001979 bool DoExecute(Args &command, CommandReturnObject &result) override {
1980 Target *target =
1981 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001982
Kate Stoneb9c1b512016-09-06 20:57:50 +00001983 if (target == nullptr) {
1984 result.AppendError("Invalid target. No existing target or breakpoints.");
1985 result.SetStatus(eReturnStatusFailed);
1986 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001987 }
1988
Kate Stoneb9c1b512016-09-06 20:57:50 +00001989 if (m_name_options.m_name.OptionWasSet()) {
1990 const char *name = m_name_options.m_name.GetCurrentValue();
1991 std::unique_lock<std::recursive_mutex> lock;
1992 target->GetBreakpointList().GetListMutex(lock);
1993
1994 BreakpointList &breakpoints = target->GetBreakpointList();
1995 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1996 if (bp_sp->MatchesName(name)) {
1997 StreamString s;
1998 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1999 s.EOL();
Zachary Turnerc1564272016-11-16 21:15:24 +00002000 result.AppendMessage(s.GetString());
Kate Stoneb9c1b512016-09-06 20:57:50 +00002001 }
2002 }
2003
2004 } else if (m_name_options.m_breakpoint.OptionWasSet()) {
2005 BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(
2006 m_name_options.m_breakpoint.GetCurrentValue());
2007 if (bp_sp) {
2008 std::vector<std::string> names;
2009 bp_sp->GetNames(names);
2010 result.AppendMessage("Names:");
2011 for (auto name : names)
2012 result.AppendMessageWithFormat(" %s\n", name.c_str());
2013 } else {
2014 result.AppendErrorWithFormat(
2015 "Could not find breakpoint %" PRId64 ".\n",
2016 m_name_options.m_breakpoint.GetCurrentValue());
2017 result.SetStatus(eReturnStatusFailed);
2018 return false;
2019 }
2020 } else {
2021 result.SetError("Must specify -N or -B option to list.");
2022 result.SetStatus(eReturnStatusFailed);
2023 return false;
2024 }
2025 return true;
2026 }
2027
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002028private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002029 BreakpointNameOptionGroup m_name_options;
2030 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002031};
2032
2033//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002034// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002035//-------------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00002036class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002037public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002038 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2039 : CommandObjectMultiword(
2040 interpreter, "name", "Commands to manage name tags for breakpoints",
2041 "breakpoint name <subcommand> [<command-options>]") {
2042 CommandObjectSP add_command_object(
2043 new CommandObjectBreakpointNameAdd(interpreter));
2044 CommandObjectSP delete_command_object(
2045 new CommandObjectBreakpointNameDelete(interpreter));
2046 CommandObjectSP list_command_object(
2047 new CommandObjectBreakpointNameList(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002048
Kate Stoneb9c1b512016-09-06 20:57:50 +00002049 LoadSubCommand("add", add_command_object);
2050 LoadSubCommand("delete", delete_command_object);
2051 LoadSubCommand("list", list_command_object);
2052 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002053
Kate Stoneb9c1b512016-09-06 20:57:50 +00002054 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002055};
2056
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002057//-------------------------------------------------------------------------
Jim Inghame14dc262016-09-12 23:10:56 +00002058// CommandObjectBreakpointRead
2059//-------------------------------------------------------------------------
Jim Ingham3acdf382016-09-22 22:20:28 +00002060#pragma mark Read::CommandOptions
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002061static OptionDefinition g_breakpoint_read_options[] = {
2062 // clang-format off
Jim Ingham3acdf382016-09-22 22:20:28 +00002063 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." },
2064 {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 +00002065 // clang-format on
2066};
2067
2068#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002069
2070class CommandObjectBreakpointRead : public CommandObjectParsed {
2071public:
2072 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2073 : CommandObjectParsed(interpreter, "breakpoint read",
2074 "Read and set the breakpoints previously saved to "
2075 "a file with \"breakpoint write\". ",
2076 nullptr),
2077 m_options() {
2078 CommandArgumentEntry arg;
2079 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2080 eArgTypeBreakpointIDRange);
2081 // Add the entry for the first argument for this command to the object's
2082 // arguments vector.
2083 m_arguments.push_back(arg);
2084 }
2085
2086 ~CommandObjectBreakpointRead() override = default;
2087
2088 Options *GetOptions() override { return &m_options; }
2089
2090 class CommandOptions : public Options {
2091 public:
2092 CommandOptions() : Options() {}
2093
2094 ~CommandOptions() override = default;
2095
Zachary Turner97206d52017-05-12 04:51:55 +00002096 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2097 ExecutionContext *execution_context) override {
2098 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002099 const int short_option = m_getopt_table[option_idx].val;
2100
2101 switch (short_option) {
2102 case 'f':
2103 m_filename.assign(option_arg);
2104 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002105 case 'N': {
Zachary Turner97206d52017-05-12 04:51:55 +00002106 Status name_error;
Jim Ingham3acdf382016-09-22 22:20:28 +00002107 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2108 name_error)) {
2109 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2110 name_error.AsCString());
2111 }
2112 m_names.push_back(option_arg);
2113 break;
2114 }
Jim Inghame14dc262016-09-12 23:10:56 +00002115 default:
2116 error.SetErrorStringWithFormat("unrecognized option '%c'",
2117 short_option);
2118 break;
2119 }
2120
2121 return error;
2122 }
2123
2124 void OptionParsingStarting(ExecutionContext *execution_context) override {
2125 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002126 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002127 }
2128
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002129 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002130 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002131 }
Jim Inghame14dc262016-09-12 23:10:56 +00002132
2133 // Instance variables to hold the values for command options.
2134
2135 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002136 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002137 };
2138
2139protected:
2140 bool DoExecute(Args &command, CommandReturnObject &result) override {
2141 Target *target = GetSelectedOrDummyTarget();
2142 if (target == nullptr) {
2143 result.AppendError("Invalid target. No existing target or breakpoints.");
2144 result.SetStatus(eReturnStatusFailed);
2145 return false;
2146 }
2147
Jim Ingham3acdf382016-09-22 22:20:28 +00002148 std::unique_lock<std::recursive_mutex> lock;
2149 target->GetBreakpointList().GetListMutex(lock);
2150
Jim Inghame14dc262016-09-12 23:10:56 +00002151 FileSpec input_spec(m_options.m_filename, true);
Jim Ingham01f16662016-09-14 19:07:35 +00002152 BreakpointIDList new_bps;
Zachary Turner97206d52017-05-12 04:51:55 +00002153 Status error = target->CreateBreakpointsFromFile(
2154 input_spec, m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002155
Jim Inghame14dc262016-09-12 23:10:56 +00002156 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002157 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002158 result.SetStatus(eReturnStatusFailed);
2159 return false;
2160 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002161
2162 Stream &output_stream = result.GetOutputStream();
2163
2164 size_t num_breakpoints = new_bps.GetSize();
2165 if (num_breakpoints == 0) {
2166 result.AppendMessage("No breakpoints added.");
2167 } else {
2168 // No breakpoint selected; show info about all currently set breakpoints.
2169 result.AppendMessage("New breakpoints:");
2170 for (size_t i = 0; i < num_breakpoints; ++i) {
2171 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2172 Breakpoint *bp = target->GetBreakpointList()
2173 .FindBreakpointByID(bp_id.GetBreakpointID())
2174 .get();
2175 if (bp)
2176 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2177 false);
2178 }
2179 }
Jim Inghame14dc262016-09-12 23:10:56 +00002180 return result.Succeeded();
2181 }
2182
2183private:
2184 CommandOptions m_options;
2185};
2186
Jim Inghame14dc262016-09-12 23:10:56 +00002187//-------------------------------------------------------------------------
2188// CommandObjectBreakpointWrite
2189//-------------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002190#pragma mark Write::CommandOptions
2191static OptionDefinition g_breakpoint_write_options[] = {
2192 // clang-format off
Jim Ingham2d3628e2016-09-22 23:42:42 +00002193 { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." },
2194 { 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 +00002195 // clang-format on
2196};
2197
2198#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002199class CommandObjectBreakpointWrite : public CommandObjectParsed {
2200public:
2201 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2202 : CommandObjectParsed(interpreter, "breakpoint write",
2203 "Write the breakpoints listed to a file that can "
2204 "be read in with \"breakpoint read\". "
2205 "If given no arguments, writes all breakpoints.",
2206 nullptr),
2207 m_options() {
2208 CommandArgumentEntry arg;
2209 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2210 eArgTypeBreakpointIDRange);
2211 // Add the entry for the first argument for this command to the object's
2212 // arguments vector.
2213 m_arguments.push_back(arg);
2214 }
2215
2216 ~CommandObjectBreakpointWrite() override = default;
2217
2218 Options *GetOptions() override { return &m_options; }
2219
2220 class CommandOptions : public Options {
2221 public:
2222 CommandOptions() : Options() {}
2223
2224 ~CommandOptions() override = default;
2225
Zachary Turner97206d52017-05-12 04:51:55 +00002226 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2227 ExecutionContext *execution_context) override {
2228 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002229 const int short_option = m_getopt_table[option_idx].val;
2230
2231 switch (short_option) {
2232 case 'f':
2233 m_filename.assign(option_arg);
2234 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002235 case 'a':
2236 m_append = true;
2237 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002238 default:
2239 error.SetErrorStringWithFormat("unrecognized option '%c'",
2240 short_option);
2241 break;
2242 }
2243
2244 return error;
2245 }
2246
2247 void OptionParsingStarting(ExecutionContext *execution_context) override {
2248 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002249 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002250 }
2251
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002252 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002253 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002254 }
Jim Inghame14dc262016-09-12 23:10:56 +00002255
2256 // Instance variables to hold the values for command options.
2257
2258 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002259 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002260 };
2261
2262protected:
2263 bool DoExecute(Args &command, CommandReturnObject &result) override {
2264 Target *target = GetSelectedOrDummyTarget();
2265 if (target == nullptr) {
2266 result.AppendError("Invalid target. No existing target or breakpoints.");
2267 result.SetStatus(eReturnStatusFailed);
2268 return false;
2269 }
2270
Jim Inghame14dc262016-09-12 23:10:56 +00002271 std::unique_lock<std::recursive_mutex> lock;
2272 target->GetBreakpointList().GetListMutex(lock);
2273
Jim Ingham01f16662016-09-14 19:07:35 +00002274 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002275 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002276 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2277 command, target, result, &valid_bp_ids);
2278
Jim Ingham01f16662016-09-14 19:07:35 +00002279 if (!result.Succeeded()) {
2280 result.SetStatus(eReturnStatusFailed);
2281 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002282 }
2283 }
Zachary Turner97206d52017-05-12 04:51:55 +00002284 Status error = target->SerializeBreakpointsToFile(
Malcolm Parsons771ef6d2016-11-02 20:34:10 +00002285 FileSpec(m_options.m_filename, true), valid_bp_ids, m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002286 if (!error.Success()) {
2287 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2288 error.AsCString());
2289 result.SetStatus(eReturnStatusFailed);
2290 }
Jim Inghame14dc262016-09-12 23:10:56 +00002291 return result.Succeeded();
2292 }
2293
2294private:
2295 CommandOptions m_options;
2296};
2297
Jim Inghame14dc262016-09-12 23:10:56 +00002298//-------------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002299// CommandObjectMultiwordBreakpoint
2300//-------------------------------------------------------------------------
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002301#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002302
Kate Stoneb9c1b512016-09-06 20:57:50 +00002303CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2304 CommandInterpreter &interpreter)
2305 : CommandObjectMultiword(
2306 interpreter, "breakpoint",
2307 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2308 "breakpoint <subcommand> [<command-options>]") {
2309 CommandObjectSP list_command_object(
2310 new CommandObjectBreakpointList(interpreter));
2311 CommandObjectSP enable_command_object(
2312 new CommandObjectBreakpointEnable(interpreter));
2313 CommandObjectSP disable_command_object(
2314 new CommandObjectBreakpointDisable(interpreter));
2315 CommandObjectSP clear_command_object(
2316 new CommandObjectBreakpointClear(interpreter));
2317 CommandObjectSP delete_command_object(
2318 new CommandObjectBreakpointDelete(interpreter));
2319 CommandObjectSP set_command_object(
2320 new CommandObjectBreakpointSet(interpreter));
2321 CommandObjectSP command_command_object(
2322 new CommandObjectBreakpointCommand(interpreter));
2323 CommandObjectSP modify_command_object(
2324 new CommandObjectBreakpointModify(interpreter));
2325 CommandObjectSP name_command_object(
2326 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002327 CommandObjectSP write_command_object(
2328 new CommandObjectBreakpointWrite(interpreter));
2329 CommandObjectSP read_command_object(
2330 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002331
Kate Stoneb9c1b512016-09-06 20:57:50 +00002332 list_command_object->SetCommandName("breakpoint list");
2333 enable_command_object->SetCommandName("breakpoint enable");
2334 disable_command_object->SetCommandName("breakpoint disable");
2335 clear_command_object->SetCommandName("breakpoint clear");
2336 delete_command_object->SetCommandName("breakpoint delete");
2337 set_command_object->SetCommandName("breakpoint set");
2338 command_command_object->SetCommandName("breakpoint command");
2339 modify_command_object->SetCommandName("breakpoint modify");
2340 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002341 write_command_object->SetCommandName("breakpoint write");
2342 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002343
Kate Stoneb9c1b512016-09-06 20:57:50 +00002344 LoadSubCommand("list", list_command_object);
2345 LoadSubCommand("enable", enable_command_object);
2346 LoadSubCommand("disable", disable_command_object);
2347 LoadSubCommand("clear", clear_command_object);
2348 LoadSubCommand("delete", delete_command_object);
2349 LoadSubCommand("set", set_command_object);
2350 LoadSubCommand("command", command_command_object);
2351 LoadSubCommand("modify", modify_command_object);
2352 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002353 LoadSubCommand("write", write_command_object);
2354 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002355}
2356
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002357CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002358
Kate Stoneb9c1b512016-09-06 20:57:50 +00002359void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2360 bool allow_locations,
2361 CommandReturnObject &result,
2362 BreakpointIDList *valid_ids) {
2363 // args can be strings representing 1). integers (for breakpoint ids)
2364 // 2). the full breakpoint & location
2365 // canonical representation
2366 // 3). the word "to" or a hyphen,
2367 // representing a range (in which case there
2368 // had *better* be an entry both before &
2369 // after of one of the first two types.
2370 // 4). A breakpoint name
2371 // If args is empty, we will use the last created breakpoint (if there is
2372 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002373
Kate Stoneb9c1b512016-09-06 20:57:50 +00002374 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002375
Zachary Turner11eb9c62016-10-05 20:03:37 +00002376 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002377 if (target->GetLastCreatedBreakpoint()) {
2378 valid_ids->AddBreakpointID(BreakpointID(
2379 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2380 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2381 } else {
2382 result.AppendError(
2383 "No breakpoint specified and no last created breakpoint.");
2384 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002385 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002386 return;
2387 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002388
Kate Stoneb9c1b512016-09-06 20:57:50 +00002389 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2390 // directly from the old ARGS to
2391 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead
2392 // generate a list of strings for
2393 // all the breakpoint ids in the range, and shove all of those breakpoint id
2394 // strings into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002395
Kate Stoneb9c1b512016-09-06 20:57:50 +00002396 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2397 result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002398
Kate Stoneb9c1b512016-09-06 20:57:50 +00002399 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2400 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002401
Kate Stoneb9c1b512016-09-06 20:57:50 +00002402 valid_ids->InsertStringArray(temp_args.GetConstArgumentVector(),
2403 temp_args.GetArgumentCount(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002404
Kate Stoneb9c1b512016-09-06 20:57:50 +00002405 // At this point, all of the breakpoint ids that the user passed in have been
2406 // converted to breakpoint IDs
2407 // and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002408
Kate Stoneb9c1b512016-09-06 20:57:50 +00002409 if (result.Succeeded()) {
2410 // Now that we've converted everything from args into a list of breakpoint
2411 // ids, go through our tentative list
2412 // of breakpoint id's and verify that they correspond to valid/currently set
2413 // breakpoints.
2414
2415 const size_t count = valid_ids->GetSize();
2416 for (size_t i = 0; i < count; ++i) {
2417 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2418 Breakpoint *breakpoint =
2419 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2420 if (breakpoint != nullptr) {
2421 const size_t num_locations = breakpoint->GetNumLocations();
2422 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2423 StreamString id_str;
2424 BreakpointID::GetCanonicalReference(
2425 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2426 i = valid_ids->GetSize() + 1;
2427 result.AppendErrorWithFormat(
2428 "'%s' is not a currently valid breakpoint/location id.\n",
2429 id_str.GetData());
2430 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002431 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002432 } else {
2433 i = valid_ids->GetSize() + 1;
2434 result.AppendErrorWithFormat(
2435 "'%d' is not a currently valid breakpoint ID.\n",
2436 cur_bp_id.GetBreakpointID());
2437 result.SetStatus(eReturnStatusFailed);
2438 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002439 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002440 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002441}