blob: e73c924de8aa4b222a47f608653015a3fa73e85a [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Chris Lattner30fdc8d2010-06-08 16:52:24 +00006//
7//===----------------------------------------------------------------------===//
8
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00009#include "CommandObjectBreakpoint.h"
10#include "CommandObjectBreakpointCommand.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000011#include "lldb/Breakpoint/Breakpoint.h"
12#include "lldb/Breakpoint/BreakpointIDList.h"
13#include "lldb/Breakpoint/BreakpointLocation.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000014#include "lldb/Host/OptionParser.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000015#include "lldb/Interpreter/CommandCompletions.h"
16#include "lldb/Interpreter/CommandInterpreter.h"
17#include "lldb/Interpreter/CommandReturnObject.h"
Pavel Labath47cbf4a2018-04-10 09:03:59 +000018#include "lldb/Interpreter/OptionArgParser.h"
Zachary Turner32abc6e2015-03-03 19:23:09 +000019#include "lldb/Interpreter/OptionValueBoolean.h"
Jim Ingham5e09c8c2014-12-16 23:40:14 +000020#include "lldb/Interpreter/OptionValueString.h"
21#include "lldb/Interpreter/OptionValueUInt64.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000022#include "lldb/Interpreter/Options.h"
Jim Ingham0e0984e2015-09-02 01:06:46 +000023#include "lldb/Target/Language.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000024#include "lldb/Target/StackFrame.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000025#include "lldb/Target/Target.h"
Jim Ingham1b54c882010-06-16 02:00:15 +000026#include "lldb/Target/Thread.h"
27#include "lldb/Target/ThreadSpec.h"
Zachary Turnerbf9a7732017-02-02 21:39:50 +000028#include "lldb/Utility/RegularExpression.h"
29#include "lldb/Utility/StreamString.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030
Jonas Devlieghere796ac802019-02-11 23:13:08 +000031#include <memory>
32#include <vector>
33
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034using namespace lldb;
35using namespace lldb_private;
36
Kate Stoneb9c1b512016-09-06 20:57:50 +000037static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
38 lldb::DescriptionLevel level) {
39 s->IndentMore();
40 bp->GetDescription(s, level, true);
41 s->IndentLess();
42 s->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043}
44
Jim Inghamb842f2e2017-09-14 20:22:49 +000045// Modifiable Breakpoint Options
Jim Inghamb842f2e2017-09-14 20:22:49 +000046#pragma mark Modify::CommandOptions
Raphael Isemannf94668e2019-07-22 10:02:09 +000047#define LLDB_OPTIONS_breakpoint_modify
48#include "CommandOptions.inc"
Raphael Isemannbd68a052019-07-28 06:24:07 +000049
Jim Inghamb842f2e2017-09-14 20:22:49 +000050class lldb_private::BreakpointOptionGroup : public OptionGroup
51{
52public:
53 BreakpointOptionGroup() :
54 OptionGroup(),
55 m_bp_opts(false) {}
56
57 ~BreakpointOptionGroup() override = default;
58
59 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
60 return llvm::makeArrayRef(g_breakpoint_modify_options);
61 }
62
63 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
64 ExecutionContext *execution_context) override {
65 Status error;
66 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
67
68 switch (short_option) {
69 case 'c':
Adrian Prantl05097242018-04-30 16:49:04 +000070 // Normally an empty breakpoint condition marks is as unset. But we need
71 // to say it was passed in.
Jim Inghamb842f2e2017-09-14 20:22:49 +000072 m_bp_opts.SetCondition(option_arg.str().c_str());
73 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
74 break;
75 case 'C':
76 m_commands.push_back(option_arg);
77 break;
78 case 'd':
79 m_bp_opts.SetEnabled(false);
80 break;
81 case 'e':
82 m_bp_opts.SetEnabled(true);
83 break;
84 case 'G': {
85 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +000086 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +000087 if (success) {
88 m_bp_opts.SetAutoContinue(value);
89 } else
90 error.SetErrorStringWithFormat(
91 "invalid boolean value '%s' passed for -G option",
92 option_arg.str().c_str());
93 }
94 break;
95 case 'i':
96 {
97 uint32_t ignore_count;
98 if (option_arg.getAsInteger(0, ignore_count))
99 error.SetErrorStringWithFormat("invalid ignore count '%s'",
100 option_arg.str().c_str());
101 else
102 m_bp_opts.SetIgnoreCount(ignore_count);
103 }
104 break;
105 case 'o': {
106 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000107 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000108 if (success) {
109 m_bp_opts.SetOneShot(value);
110 } else
111 error.SetErrorStringWithFormat(
112 "invalid boolean value '%s' passed for -o option",
113 option_arg.str().c_str());
114 } break;
115 case 't':
116 {
117 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
118 if (option_arg[0] != '\0') {
119 if (option_arg.getAsInteger(0, thread_id))
120 error.SetErrorStringWithFormat("invalid thread id string '%s'",
121 option_arg.str().c_str());
122 }
123 m_bp_opts.SetThreadID(thread_id);
124 }
125 break;
126 case 'T':
127 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
128 break;
129 case 'q':
130 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
131 break;
132 case 'x':
133 {
134 uint32_t thread_index = UINT32_MAX;
135 if (option_arg[0] != '\n') {
136 if (option_arg.getAsInteger(0, thread_index))
137 error.SetErrorStringWithFormat("invalid thread index string '%s'",
138 option_arg.str().c_str());
139 }
140 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
141 }
142 break;
143 default:
Raphael Isemann36162012019-08-22 08:08:05 +0000144 llvm_unreachable("Unimplemented option");
Jim Inghamb842f2e2017-09-14 20:22:49 +0000145 }
146
147 return error;
148 }
149
150 void OptionParsingStarting(ExecutionContext *execution_context) override {
151 m_bp_opts.Clear();
152 m_commands.clear();
153 }
154
155 Status OptionParsingFinished(ExecutionContext *execution_context) override {
156 if (!m_commands.empty())
157 {
158 if (!m_commands.empty())
159 {
Jonas Devliegherea8f3ae72019-08-14 22:19:23 +0000160 auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
Jim Inghamb842f2e2017-09-14 20:22:49 +0000161
162 for (std::string &str : m_commands)
163 cmd_data->user_source.AppendString(str);
164
165 cmd_data->stop_on_error = true;
166 m_bp_opts.SetCommandDataCallback(cmd_data);
167 }
168 }
169 return Status();
170 }
171
172 const BreakpointOptions &GetBreakpointOptions()
173 {
174 return m_bp_opts;
175 }
176
177 std::vector<std::string> m_commands;
178 BreakpointOptions m_bp_opts;
179
180};
Raphael Isemannbd68a052019-07-28 06:24:07 +0000181
Raphael Isemannf94668e2019-07-22 10:02:09 +0000182#define LLDB_OPTIONS_breakpoint_dummy
183#include "CommandOptions.inc"
Jim Inghamb842f2e2017-09-14 20:22:49 +0000184
185class BreakpointDummyOptionGroup : public OptionGroup
186{
187public:
188 BreakpointDummyOptionGroup() :
189 OptionGroup() {}
190
191 ~BreakpointDummyOptionGroup() override = default;
192
193 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
194 return llvm::makeArrayRef(g_breakpoint_dummy_options);
195 }
196
197 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
198 ExecutionContext *execution_context) override {
199 Status error;
200 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
201
202 switch (short_option) {
203 case 'D':
204 m_use_dummy = true;
205 break;
206 default:
Raphael Isemann36162012019-08-22 08:08:05 +0000207 llvm_unreachable("Unimplemented option");
Jim Inghamb842f2e2017-09-14 20:22:49 +0000208 }
209
210 return error;
211 }
212
213 void OptionParsingStarting(ExecutionContext *execution_context) override {
214 m_use_dummy = false;
215 }
216
217 bool m_use_dummy;
218
219};
220
Raphael Isemannf94668e2019-07-22 10:02:09 +0000221#define LLDB_OPTIONS_breakpoint_set
222#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000223
Jim Ingham5a988412012-06-08 21:56:10 +0000224// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000225
Kate Stoneb9c1b512016-09-06 20:57:50 +0000226class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000227public:
Fangrui Songefe8e7e2019-05-14 08:55:50 +0000228 enum BreakpointSetType {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229 eSetTypeInvalid,
230 eSetTypeFileAndLine,
231 eSetTypeAddress,
232 eSetTypeFunctionName,
233 eSetTypeFunctionRegexp,
234 eSetTypeSourceRegexp,
Jim Ingham3815e702018-09-13 21:35:32 +0000235 eSetTypeException,
236 eSetTypeScripted,
Fangrui Songefe8e7e2019-05-14 08:55:50 +0000237 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000238
Kate Stoneb9c1b512016-09-06 20:57:50 +0000239 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
240 : CommandObjectParsed(
241 interpreter, "breakpoint set",
242 "Sets a breakpoint or set of breakpoints in the executable.",
243 "breakpoint set <cmd-options>"),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000244 m_bp_opts(), m_options() {
245 // We're picking up all the normal options, commands and disable.
246 m_all_options.Append(&m_bp_opts,
247 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
248 LLDB_OPT_SET_ALL);
249 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
250 m_all_options.Append(&m_options);
251 m_all_options.Finalize();
252 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000253
254 ~CommandObjectBreakpointSet() override = default;
255
Jim Inghamb842f2e2017-09-14 20:22:49 +0000256 Options *GetOptions() override { return &m_all_options; }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000257
Jim Inghamb842f2e2017-09-14 20:22:49 +0000258 class CommandOptions : public OptionGroup {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000259 public:
260 CommandOptions()
Jim Inghamb842f2e2017-09-14 20:22:49 +0000261 : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000262 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
263 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
265 m_exception_language(eLanguageTypeUnknown),
266 m_language(lldb::eLanguageTypeUnknown),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000267 m_skip_prologue(eLazyBoolCalculate),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000268 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
269
270 ~CommandOptions() override = default;
271
Zachary Turner97206d52017-05-12 04:51:55 +0000272 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
273 ExecutionContext *execution_context) override {
274 Status error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000275 const int short_option = g_breakpoint_set_options[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000276
277 switch (short_option) {
278 case 'a': {
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000279 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
280 LLDB_INVALID_ADDRESS, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000281 } break;
282
283 case 'A':
284 m_all_files = true;
285 break;
286
287 case 'b':
288 m_func_names.push_back(option_arg);
289 m_func_name_type_mask |= eFunctionNameTypeBase;
290 break;
291
Zachary Turnerfe114832016-11-12 16:56:47 +0000292 case 'C':
293 if (option_arg.getAsInteger(0, m_column))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000294 error.SetErrorStringWithFormat("invalid column number: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000295 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000297
Kate Stoneb9c1b512016-09-06 20:57:50 +0000298 case 'E': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000299 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000300
301 switch (language) {
302 case eLanguageTypeC89:
303 case eLanguageTypeC:
304 case eLanguageTypeC99:
305 case eLanguageTypeC11:
306 m_exception_language = eLanguageTypeC;
307 break;
308 case eLanguageTypeC_plus_plus:
309 case eLanguageTypeC_plus_plus_03:
310 case eLanguageTypeC_plus_plus_11:
311 case eLanguageTypeC_plus_plus_14:
312 m_exception_language = eLanguageTypeC_plus_plus;
313 break;
314 case eLanguageTypeObjC:
315 m_exception_language = eLanguageTypeObjC;
316 break;
317 case eLanguageTypeObjC_plus_plus:
318 error.SetErrorStringWithFormat(
319 "Set exception breakpoints separately for c++ and objective-c");
320 break;
321 case eLanguageTypeUnknown:
322 error.SetErrorStringWithFormat(
323 "Unknown language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000324 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325 break;
326 default:
327 error.SetErrorStringWithFormat(
328 "Unsupported language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000329 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000330 }
331 } break;
332
333 case 'f':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000334 m_filenames.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000335 break;
336
337 case 'F':
338 m_func_names.push_back(option_arg);
339 m_func_name_type_mask |= eFunctionNameTypeFull;
340 break;
Jim Inghamf08f5c92017-08-03 18:13:24 +0000341
Kate Stoneb9c1b512016-09-06 20:57:50 +0000342 case 'h': {
343 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000344 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000345 if (!success)
346 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000347 "Invalid boolean value for on-catch option: '%s'",
348 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000349 } break;
350
351 case 'H':
352 m_hardware = true;
353 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000354
355 case 'k': {
356 if (m_current_key.empty())
357 m_current_key.assign(option_arg);
358 else
359 error.SetErrorStringWithFormat("Key: %s missing value.",
360 m_current_key.c_str());
361
362 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363 case 'K': {
364 bool success;
365 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000366 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 if (value)
368 m_skip_prologue = eLazyBoolYes;
369 else
370 m_skip_prologue = eLazyBoolNo;
371
372 if (!success)
373 error.SetErrorStringWithFormat(
374 "Invalid boolean value for skip prologue option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000375 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000376 } break;
377
Zachary Turnerfe114832016-11-12 16:56:47 +0000378 case 'l':
379 if (option_arg.getAsInteger(0, m_line_num))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380 error.SetErrorStringWithFormat("invalid line number: %s.",
Zachary Turnerfe114832016-11-12 16:56:47 +0000381 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000382 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000383
384 case 'L':
Zachary Turnerfe114832016-11-12 16:56:47 +0000385 m_language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386 if (m_language == eLanguageTypeUnknown)
387 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000388 "Unknown language type: '%s' for breakpoint",
389 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000390 break;
391
392 case 'm': {
393 bool success;
394 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000395 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396 if (value)
397 m_move_to_nearest_code = eLazyBoolYes;
398 else
399 m_move_to_nearest_code = eLazyBoolNo;
400
401 if (!success)
402 error.SetErrorStringWithFormat(
403 "Invalid boolean value for move-to-nearest-code option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000404 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000405 break;
406 }
407
408 case 'M':
409 m_func_names.push_back(option_arg);
410 m_func_name_type_mask |= eFunctionNameTypeMethod;
411 break;
412
413 case 'n':
414 m_func_names.push_back(option_arg);
415 m_func_name_type_mask |= eFunctionNameTypeAuto;
416 break;
417
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000418 case 'N': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000419 if (BreakpointID::StringIsBreakpointName(option_arg, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000420 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000421 else
422 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000423 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000425 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000426
427 case 'R': {
428 lldb::addr_t tmp_offset_addr;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000429 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
430 option_arg, 0, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000431 if (error.Success())
432 m_offset_addr = tmp_offset_addr;
433 } break;
434
Kate Stoneb9c1b512016-09-06 20:57:50 +0000435 case 'O':
Zachary Turnerfe114832016-11-12 16:56:47 +0000436 m_exception_extra_args.AppendArgument("-O");
437 m_exception_extra_args.AppendArgument(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000438 break;
439
440 case 'p':
441 m_source_text_regexp.assign(option_arg);
442 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000443
444 case 'P':
445 m_python_class.assign(option_arg);
446 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000447
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 case 'r':
449 m_func_regexp.assign(option_arg);
450 break;
451
452 case 's':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000453 m_modules.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000454 break;
455
456 case 'S':
457 m_func_names.push_back(option_arg);
458 m_func_name_type_mask |= eFunctionNameTypeSelector;
459 break;
460
Jim Ingham3815e702018-09-13 21:35:32 +0000461 case 'v': {
462 if (!m_current_key.empty()) {
463 m_extra_args_sp->AddStringItem(m_current_key, option_arg);
464 m_current_key.clear();
465 }
466 else
467 error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
468 option_arg.str().c_str());
469 } break;
470
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471 case 'w': {
472 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000473 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000474 if (!success)
475 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000476 "Invalid boolean value for on-throw option: '%s'",
477 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000478 } break;
479
Kate Stoneb9c1b512016-09-06 20:57:50 +0000480 case 'X':
481 m_source_regex_func_names.insert(option_arg);
482 break;
483
484 default:
Raphael Isemann36162012019-08-22 08:08:05 +0000485 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000486 }
487
488 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000489 }
490
Kate Stoneb9c1b512016-09-06 20:57:50 +0000491 void OptionParsingStarting(ExecutionContext *execution_context) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000492 m_filenames.Clear();
493 m_line_num = 0;
494 m_column = 0;
495 m_func_names.clear();
496 m_func_name_type_mask = eFunctionNameTypeNone;
497 m_func_regexp.clear();
498 m_source_text_regexp.clear();
499 m_modules.Clear();
500 m_load_addr = LLDB_INVALID_ADDRESS;
501 m_offset_addr = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000502 m_catch_bp = false;
503 m_throw_bp = true;
504 m_hardware = false;
505 m_exception_language = eLanguageTypeUnknown;
506 m_language = lldb::eLanguageTypeUnknown;
507 m_skip_prologue = eLazyBoolCalculate;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000508 m_breakpoint_names.clear();
509 m_all_files = false;
510 m_exception_extra_args.Clear();
511 m_move_to_nearest_code = eLazyBoolCalculate;
512 m_source_regex_func_names.clear();
Jim Ingham3815e702018-09-13 21:35:32 +0000513 m_python_class.clear();
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000514 m_extra_args_sp = std::make_shared<StructuredData::Dictionary>();
Jim Ingham3815e702018-09-13 21:35:32 +0000515 m_current_key.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000516 }
517
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000518 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000519 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000520 }
Jim Ingham5a988412012-06-08 21:56:10 +0000521
Kate Stoneb9c1b512016-09-06 20:57:50 +0000522 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000523
Kate Stoneb9c1b512016-09-06 20:57:50 +0000524 std::string m_condition;
525 FileSpecList m_filenames;
526 uint32_t m_line_num;
527 uint32_t m_column;
528 std::vector<std::string> m_func_names;
529 std::vector<std::string> m_breakpoint_names;
Zachary Turner117b1fa2018-10-25 20:45:40 +0000530 lldb::FunctionNameType m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000531 std::string m_func_regexp;
532 std::string m_source_text_regexp;
533 FileSpecList m_modules;
534 lldb::addr_t m_load_addr;
535 lldb::addr_t m_offset_addr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000536 bool m_catch_bp;
537 bool m_throw_bp;
538 bool m_hardware; // Request to use hardware breakpoints
539 lldb::LanguageType m_exception_language;
540 lldb::LanguageType m_language;
541 LazyBool m_skip_prologue;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000542 bool m_all_files;
543 Args m_exception_extra_args;
544 LazyBool m_move_to_nearest_code;
545 std::unordered_set<std::string> m_source_regex_func_names;
Jim Ingham3815e702018-09-13 21:35:32 +0000546 std::string m_python_class;
547 StructuredData::DictionarySP m_extra_args_sp;
548 std::string m_current_key;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000549 };
Jim Ingham5a988412012-06-08 21:56:10 +0000550
551protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000553 Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
Jim Ingham5a988412012-06-08 21:56:10 +0000554
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555 // The following are the various types of breakpoints that could be set:
556 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
557 // 2). -a [-s -g] (setting breakpoint by address)
558 // 3). -n [-s -g] (setting breakpoint by function name)
559 // 4). -r [-s -g] (setting breakpoint by function name regular
560 // expression)
561 // 5). -p -f (setting a breakpoint by comparing a reg-exp
562 // to source text)
563 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
564 // given language.)
565
566 BreakpointSetType break_type = eSetTypeInvalid;
567
Jim Ingham3815e702018-09-13 21:35:32 +0000568 if (!m_options.m_python_class.empty())
569 break_type = eSetTypeScripted;
570 else if (m_options.m_line_num != 0)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000571 break_type = eSetTypeFileAndLine;
572 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
573 break_type = eSetTypeAddress;
574 else if (!m_options.m_func_names.empty())
575 break_type = eSetTypeFunctionName;
576 else if (!m_options.m_func_regexp.empty())
577 break_type = eSetTypeFunctionRegexp;
578 else if (!m_options.m_source_text_regexp.empty())
579 break_type = eSetTypeSourceRegexp;
580 else if (m_options.m_exception_language != eLanguageTypeUnknown)
581 break_type = eSetTypeException;
582
Jim Inghamb842f2e2017-09-14 20:22:49 +0000583 BreakpointSP bp_sp = nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000584 FileSpec module_spec;
585 const bool internal = false;
586
587 // If the user didn't specify skip-prologue, having an offset should turn
588 // that off.
589 if (m_options.m_offset_addr != 0 &&
590 m_options.m_skip_prologue == eLazyBoolCalculate)
591 m_options.m_skip_prologue = eLazyBoolNo;
592
593 switch (break_type) {
594 case eSetTypeFileAndLine: // Breakpoint by source position
595 {
596 FileSpec file;
597 const size_t num_files = m_options.m_filenames.GetSize();
598 if (num_files == 0) {
599 if (!GetDefaultFile(target, file, result)) {
600 result.AppendError("No file supplied and no default file available.");
601 result.SetStatus(eReturnStatusFailed);
602 return false;
603 }
604 } else if (num_files > 1) {
605 result.AppendError("Only one file at a time is allowed for file and "
606 "line breakpoints.");
607 result.SetStatus(eReturnStatusFailed);
608 return false;
609 } else
610 file = m_options.m_filenames.GetFileSpecAtIndex(0);
611
612 // Only check for inline functions if
613 LazyBool check_inlines = eLazyBoolCalculate;
614
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000615 bp_sp = target.CreateBreakpoint(
616 &(m_options.m_modules), file, m_options.m_line_num,
617 m_options.m_column, m_options.m_offset_addr, check_inlines,
618 m_options.m_skip_prologue, internal, m_options.m_hardware,
619 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000620 } break;
621
622 case eSetTypeAddress: // Breakpoint by address
623 {
624 // If a shared library has been specified, make an lldb_private::Address
Jim Inghamb842f2e2017-09-14 20:22:49 +0000625 // with the library, and use that. That way the address breakpoint
626 // will track the load location of the library.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000627 size_t num_modules_specified = m_options.m_modules.GetSize();
628 if (num_modules_specified == 1) {
629 const FileSpec *file_spec =
630 m_options.m_modules.GetFileSpecPointerAtIndex(0);
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000631 bp_sp = target.CreateAddressInModuleBreakpoint(
632 m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000633 } else if (num_modules_specified == 0) {
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000634 bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
635 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000636 } else {
637 result.AppendError("Only one shared library can be specified for "
638 "address breakpoints.");
639 result.SetStatus(eReturnStatusFailed);
640 return false;
641 }
642 break;
643 }
644 case eSetTypeFunctionName: // Breakpoint by function name
645 {
Zachary Turner117b1fa2018-10-25 20:45:40 +0000646 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000647
648 if (name_type_mask == 0)
649 name_type_mask = eFunctionNameTypeAuto;
650
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000651 bp_sp = target.CreateBreakpoint(
652 &(m_options.m_modules), &(m_options.m_filenames),
653 m_options.m_func_names, name_type_mask, m_options.m_language,
654 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
655 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 } break;
657
658 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
659 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000660 {
Zachary Turner95eae422016-09-21 16:01:28 +0000661 RegularExpression regexp(m_options.m_func_regexp);
Jonas Devlieghere3af3f1e2019-08-16 21:25:36 +0000662 if (llvm::Error err = regexp.GetError()) {
Jim Inghame14dc262016-09-12 23:10:56 +0000663 result.AppendErrorWithFormat(
664 "Function name regular expression could not be compiled: \"%s\"",
Jonas Devlieghere3af3f1e2019-08-16 21:25:36 +0000665 llvm::toString(std::move(err)).c_str());
Jim Inghame14dc262016-09-12 23:10:56 +0000666 result.SetStatus(eReturnStatusFailed);
667 return false;
668 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000669
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000670 bp_sp = target.CreateFuncRegexBreakpoint(
Jan Kratochvil5aa1d812019-09-04 09:47:18 +0000671 &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000672 m_options.m_language, m_options.m_skip_prologue, internal,
673 m_options.m_hardware);
Jim Inghame14dc262016-09-12 23:10:56 +0000674 }
675 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000676 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
677 {
678 const size_t num_files = m_options.m_filenames.GetSize();
679
680 if (num_files == 0 && !m_options.m_all_files) {
681 FileSpec file;
682 if (!GetDefaultFile(target, file, result)) {
683 result.AppendError(
684 "No files provided and could not find default file.");
685 result.SetStatus(eReturnStatusFailed);
686 return false;
687 } else {
688 m_options.m_filenames.Append(file);
689 }
690 }
691
Zachary Turner95eae422016-09-21 16:01:28 +0000692 RegularExpression regexp(m_options.m_source_text_regexp);
Jonas Devlieghere3af3f1e2019-08-16 21:25:36 +0000693 if (llvm::Error err = regexp.GetError()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000694 result.AppendErrorWithFormat(
695 "Source text regular expression could not be compiled: \"%s\"",
Jonas Devlieghere3af3f1e2019-08-16 21:25:36 +0000696 llvm::toString(std::move(err)).c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000697 result.SetStatus(eReturnStatusFailed);
698 return false;
699 }
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000700 bp_sp = target.CreateSourceRegexBreakpoint(
701 &(m_options.m_modules), &(m_options.m_filenames),
Jan Kratochvil5aa1d812019-09-04 09:47:18 +0000702 m_options.m_source_regex_func_names, std::move(regexp), internal,
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000703 m_options.m_hardware, m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000704 } break;
705 case eSetTypeException: {
Zachary Turner97206d52017-05-12 04:51:55 +0000706 Status precond_error;
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000707 bp_sp = target.CreateExceptionBreakpoint(
708 m_options.m_exception_language, m_options.m_catch_bp,
709 m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
710 &precond_error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000711 if (precond_error.Fail()) {
712 result.AppendErrorWithFormat(
713 "Error setting extra exception arguments: %s",
714 precond_error.AsCString());
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000715 target.RemoveBreakpointByID(bp_sp->GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000716 result.SetStatus(eReturnStatusFailed);
717 return false;
718 }
719 } break;
Jim Ingham3815e702018-09-13 21:35:32 +0000720 case eSetTypeScripted: {
721
722 Status error;
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000723 bp_sp = target.CreateScriptedBreakpoint(
724 m_options.m_python_class, &(m_options.m_modules),
725 &(m_options.m_filenames), false, m_options.m_hardware,
726 m_options.m_extra_args_sp, &error);
Jim Ingham3815e702018-09-13 21:35:32 +0000727 if (error.Fail()) {
728 result.AppendErrorWithFormat(
729 "Error setting extra exception arguments: %s",
730 error.AsCString());
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000731 target.RemoveBreakpointByID(bp_sp->GetID());
Jim Ingham3815e702018-09-13 21:35:32 +0000732 result.SetStatus(eReturnStatusFailed);
733 return false;
734 }
735 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000736 default:
737 break;
738 }
739
740 // Now set the various options that were passed in:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000741 if (bp_sp) {
742 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000743
744 if (!m_options.m_breakpoint_names.empty()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000745 Status name_error;
Jim Inghamff9a91e2016-09-21 01:21:19 +0000746 for (auto name : m_options.m_breakpoint_names) {
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000747 target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000748 if (name_error.Fail()) {
749 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
750 name.c_str());
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000751 target.RemoveBreakpointByID(bp_sp->GetID());
Jim Inghamff9a91e2016-09-21 01:21:19 +0000752 result.SetStatus(eReturnStatusFailed);
753 return false;
754 }
755 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000756 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000757 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000758
759 if (bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000760 Stream &output_stream = result.GetOutputStream();
761 const bool show_locations = false;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000762 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000763 show_locations);
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000764 if (&target == &GetDummyTarget())
Kate Stoneb9c1b512016-09-06 20:57:50 +0000765 output_stream.Printf("Breakpoint set in dummy target, will get copied "
766 "into future targets.\n");
767 else {
Adrian Prantl05097242018-04-30 16:49:04 +0000768 // Don't print out this warning for exception breakpoints. They can
769 // get set before the target is set, but we won't know how to actually
770 // set the breakpoint till we run.
Jim Inghamb842f2e2017-09-14 20:22:49 +0000771 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000772 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
773 "actual locations.\n");
774 }
775 }
776 result.SetStatus(eReturnStatusSuccessFinishResult);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000777 } else if (!bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000778 result.AppendError("Breakpoint creation failed: No breakpoint created.");
779 result.SetStatus(eReturnStatusFailed);
780 }
781
782 return result.Succeeded();
783 }
784
Jim Ingham5a988412012-06-08 21:56:10 +0000785private:
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000786 bool GetDefaultFile(Target &target, FileSpec &file,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000787 CommandReturnObject &result) {
788 uint32_t default_line;
Adrian Prantl05097242018-04-30 16:49:04 +0000789 // First use the Source Manager's default file. Then use the current stack
790 // frame's file.
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000791 if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000792 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
793 if (cur_frame == nullptr) {
794 result.AppendError(
795 "No selected frame to use to find the default file.");
796 result.SetStatus(eReturnStatusFailed);
797 return false;
798 } else if (!cur_frame->HasDebugInformation()) {
799 result.AppendError("Cannot use the selected frame to find the default "
800 "file, it has no debug info.");
801 result.SetStatus(eReturnStatusFailed);
802 return false;
803 } else {
804 const SymbolContext &sc =
805 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
806 if (sc.line_entry.file) {
807 file = sc.line_entry.file;
808 } else {
809 result.AppendError("Can't find the file for the selected frame to "
810 "use as the default file.");
811 result.SetStatus(eReturnStatusFailed);
812 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000813 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000814 }
Jim Ingham5a988412012-06-08 21:56:10 +0000815 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000816 return true;
817 }
818
Jim Inghamb842f2e2017-09-14 20:22:49 +0000819 BreakpointOptionGroup m_bp_opts;
820 BreakpointDummyOptionGroup m_dummy_options;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000821 CommandOptions m_options;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000822 OptionGroupOptions m_all_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000823};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000824
Jim Ingham5a988412012-06-08 21:56:10 +0000825// CommandObjectBreakpointModify
Jim Ingham5a988412012-06-08 21:56:10 +0000826#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000827
Kate Stoneb9c1b512016-09-06 20:57:50 +0000828class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000829public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000830 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
831 : CommandObjectParsed(interpreter, "breakpoint modify",
832 "Modify the options on a breakpoint or set of "
833 "breakpoints in the executable. "
834 "If no breakpoint is specified, acts on the last "
835 "created breakpoint. "
836 "With the exception of -e, -d and -i, passing an "
837 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000838 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000839 m_options() {
840 CommandArgumentEntry arg;
841 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
842 eArgTypeBreakpointIDRange);
843 // Add the entry for the first argument for this command to the object's
844 // arguments vector.
845 m_arguments.push_back(arg);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000846
847 m_options.Append(&m_bp_opts,
848 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
849 LLDB_OPT_SET_ALL);
850 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
851 m_options.Finalize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000852 }
853
854 ~CommandObjectBreakpointModify() override = default;
855
856 Options *GetOptions() override { return &m_options; }
857
Jim Ingham5a988412012-06-08 21:56:10 +0000858protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000859 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000860 Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000861
Kate Stoneb9c1b512016-09-06 20:57:50 +0000862 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000863 target.GetBreakpointList().GetListMutex(lock);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000864
865 BreakpointIDList valid_bp_ids;
866
867 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000868 command, &target, result, &valid_bp_ids,
Jim Inghamb842f2e2017-09-14 20:22:49 +0000869 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000870
871 if (result.Succeeded()) {
872 const size_t count = valid_bp_ids.GetSize();
873 for (size_t i = 0; i < count; ++i) {
874 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
875
876 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
877 Breakpoint *bp =
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000878 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000879 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
880 BreakpointLocation *location =
881 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +0000882 if (location)
883 location->GetLocationOptions()
884 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000885 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000886 bp->GetOptions()
887 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000888 }
889 }
890 }
891 }
892
893 return result.Succeeded();
894 }
895
Jim Ingham5a988412012-06-08 21:56:10 +0000896private:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000897 BreakpointOptionGroup m_bp_opts;
898 BreakpointDummyOptionGroup m_dummy_opts;
899 OptionGroupOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000900};
Johnny Chen7d49c9c2012-05-25 21:10:46 +0000901
Jim Ingham5a988412012-06-08 21:56:10 +0000902// CommandObjectBreakpointEnable
Jim Ingham5a988412012-06-08 21:56:10 +0000903#pragma mark Enable
904
Kate Stoneb9c1b512016-09-06 20:57:50 +0000905class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000906public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000907 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
908 : CommandObjectParsed(interpreter, "enable",
909 "Enable the specified disabled breakpoint(s). If "
910 "no breakpoints are specified, enable all of them.",
911 nullptr) {
912 CommandArgumentEntry arg;
913 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
914 eArgTypeBreakpointIDRange);
915 // Add the entry for the first argument for this command to the object's
916 // arguments vector.
917 m_arguments.push_back(arg);
918 }
Jim Ingham5a988412012-06-08 21:56:10 +0000919
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +0000921
922protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000923 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000924 Target &target = GetSelectedOrDummyTarget();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000925
926 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000927 target.GetBreakpointList().GetListMutex(lock);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000928
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000929 const BreakpointList &breakpoints = target.GetBreakpointList();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000930
931 size_t num_breakpoints = breakpoints.GetSize();
932
933 if (num_breakpoints == 0) {
934 result.AppendError("No breakpoints exist to be enabled.");
935 result.SetStatus(eReturnStatusFailed);
936 return false;
937 }
938
Zachary Turner11eb9c62016-10-05 20:03:37 +0000939 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000940 // No breakpoint selected; enable all currently set breakpoints.
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000941 target.EnableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000942 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
943 " breakpoints)\n",
944 (uint64_t)num_breakpoints);
945 result.SetStatus(eReturnStatusSuccessFinishNoResult);
946 } else {
947 // Particular breakpoint selected; enable that breakpoint.
948 BreakpointIDList valid_bp_ids;
949 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000950 command, &target, result, &valid_bp_ids,
Jim Inghamb842f2e2017-09-14 20:22:49 +0000951 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000952
953 if (result.Succeeded()) {
954 int enable_count = 0;
955 int loc_count = 0;
956 const size_t count = valid_bp_ids.GetSize();
957 for (size_t i = 0; i < count; ++i) {
958 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
959
960 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
961 Breakpoint *breakpoint =
Raphael Isemanncb2380c2019-08-26 18:12:44 +0000962 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000963 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
964 BreakpointLocation *location =
965 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
966 if (location) {
967 location->SetEnabled(true);
968 ++loc_count;
969 }
970 } else {
971 breakpoint->SetEnabled(true);
972 ++enable_count;
973 }
974 }
975 }
976 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
977 enable_count + loc_count);
978 result.SetStatus(eReturnStatusSuccessFinishNoResult);
979 }
980 }
981
982 return result.Succeeded();
983 }
Jim Ingham5a988412012-06-08 21:56:10 +0000984};
985
Jim Ingham5a988412012-06-08 21:56:10 +0000986// CommandObjectBreakpointDisable
Jim Ingham5a988412012-06-08 21:56:10 +0000987#pragma mark Disable
988
Kate Stoneb9c1b512016-09-06 20:57:50 +0000989class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000990public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000991 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
992 : CommandObjectParsed(
993 interpreter, "breakpoint disable",
994 "Disable the specified breakpoint(s) without deleting "
995 "them. If none are specified, disable all "
996 "breakpoints.",
997 nullptr) {
998 SetHelpLong(
999 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001000If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001001 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001002
Kate Stone7428a182016-07-14 22:03:10 +00001003)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001004 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001005regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001006 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001007
1008 (lldb) break disable 1
1009 (lldb) break enable 1.1
1010
1011execution will NOT stop at location 1.1. To achieve that, type:
1012
1013 (lldb) break disable 1.*
1014 (lldb) break enable 1.1
1015
Kate Stone7428a182016-07-14 22:03:10 +00001016)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001017 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001018the second re-enables the first location.");
1019
Kate Stoneb9c1b512016-09-06 20:57:50 +00001020 CommandArgumentEntry arg;
1021 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1022 eArgTypeBreakpointIDRange);
1023 // Add the entry for the first argument for this command to the object's
1024 // arguments vector.
1025 m_arguments.push_back(arg);
1026 }
Jim Ingham5a988412012-06-08 21:56:10 +00001027
Kate Stoneb9c1b512016-09-06 20:57:50 +00001028 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001029
1030protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001031 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001032 Target &target = GetSelectedOrDummyTarget();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001033 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001034 target.GetBreakpointList().GetListMutex(lock);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001035
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001036 const BreakpointList &breakpoints = target.GetBreakpointList();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001037 size_t num_breakpoints = breakpoints.GetSize();
1038
1039 if (num_breakpoints == 0) {
1040 result.AppendError("No breakpoints exist to be disabled.");
1041 result.SetStatus(eReturnStatusFailed);
1042 return false;
1043 }
1044
Zachary Turner11eb9c62016-10-05 20:03:37 +00001045 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001046 // No breakpoint selected; disable all currently set breakpoints.
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001047 target.DisableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001048 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1049 " breakpoints)\n",
1050 (uint64_t)num_breakpoints);
1051 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1052 } else {
1053 // Particular breakpoint selected; disable that breakpoint.
1054 BreakpointIDList valid_bp_ids;
1055
1056 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001057 command, &target, result, &valid_bp_ids,
Jim Inghamb842f2e2017-09-14 20:22:49 +00001058 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001059
1060 if (result.Succeeded()) {
1061 int disable_count = 0;
1062 int loc_count = 0;
1063 const size_t count = valid_bp_ids.GetSize();
1064 for (size_t i = 0; i < count; ++i) {
1065 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1066
1067 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1068 Breakpoint *breakpoint =
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001069 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001070 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1071 BreakpointLocation *location =
1072 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1073 if (location) {
1074 location->SetEnabled(false);
1075 ++loc_count;
1076 }
1077 } else {
1078 breakpoint->SetEnabled(false);
1079 ++disable_count;
1080 }
1081 }
1082 }
1083 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1084 disable_count + loc_count);
1085 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1086 }
1087 }
1088
1089 return result.Succeeded();
1090 }
Jim Ingham5a988412012-06-08 21:56:10 +00001091};
1092
Jim Ingham5a988412012-06-08 21:56:10 +00001093// CommandObjectBreakpointList
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001094
1095#pragma mark List::CommandOptions
Raphael Isemann6f4fb4e2019-07-12 15:30:55 +00001096#define LLDB_OPTIONS_breakpoint_list
Raphael Isemannc5a2d742019-07-16 09:27:02 +00001097#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001098
Jim Ingham5a988412012-06-08 21:56:10 +00001099#pragma mark List
1100
Kate Stoneb9c1b512016-09-06 20:57:50 +00001101class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001102public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001103 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1104 : CommandObjectParsed(
1105 interpreter, "breakpoint list",
1106 "List some or all breakpoints at configurable levels of detail.",
1107 nullptr),
1108 m_options() {
1109 CommandArgumentEntry arg;
1110 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001111
Kate Stoneb9c1b512016-09-06 20:57:50 +00001112 // Define the first (and only) variant of this arg.
1113 bp_id_arg.arg_type = eArgTypeBreakpointID;
1114 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001115
Kate Stoneb9c1b512016-09-06 20:57:50 +00001116 // There is only one variant this argument could be; put it into the
1117 // argument entry.
1118 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001119
Kate Stoneb9c1b512016-09-06 20:57:50 +00001120 // Push the data for the first argument into the m_arguments vector.
1121 m_arguments.push_back(arg);
1122 }
1123
1124 ~CommandObjectBreakpointList() override = default;
1125
1126 Options *GetOptions() override { return &m_options; }
1127
1128 class CommandOptions : public Options {
1129 public:
1130 CommandOptions()
1131 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001132 }
1133
Kate Stoneb9c1b512016-09-06 20:57:50 +00001134 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001135
Zachary Turner97206d52017-05-12 04:51:55 +00001136 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1137 ExecutionContext *execution_context) override {
1138 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001139 const int short_option = m_getopt_table[option_idx].val;
1140
1141 switch (short_option) {
1142 case 'b':
1143 m_level = lldb::eDescriptionLevelBrief;
1144 break;
1145 case 'D':
1146 m_use_dummy = true;
1147 break;
1148 case 'f':
1149 m_level = lldb::eDescriptionLevelFull;
1150 break;
1151 case 'v':
1152 m_level = lldb::eDescriptionLevelVerbose;
1153 break;
1154 case 'i':
1155 m_internal = true;
1156 break;
1157 default:
Raphael Isemann36162012019-08-22 08:08:05 +00001158 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +00001159 }
1160
1161 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001162 }
Jim Ingham5a988412012-06-08 21:56:10 +00001163
Kate Stoneb9c1b512016-09-06 20:57:50 +00001164 void OptionParsingStarting(ExecutionContext *execution_context) override {
1165 m_level = lldb::eDescriptionLevelFull;
1166 m_internal = false;
1167 m_use_dummy = false;
1168 }
Jim Ingham5a988412012-06-08 21:56:10 +00001169
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001170 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001171 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001172 }
Jim Ingham5a988412012-06-08 21:56:10 +00001173
Kate Stoneb9c1b512016-09-06 20:57:50 +00001174 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001175
Kate Stoneb9c1b512016-09-06 20:57:50 +00001176 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001177
Kate Stoneb9c1b512016-09-06 20:57:50 +00001178 bool m_internal;
1179 bool m_use_dummy;
1180 };
Jim Ingham5a988412012-06-08 21:56:10 +00001181
1182protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001183 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001184 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001185
Kate Stoneb9c1b512016-09-06 20:57:50 +00001186 const BreakpointList &breakpoints =
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001187 target.GetBreakpointList(m_options.m_internal);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001188 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001189 target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001190
1191 size_t num_breakpoints = breakpoints.GetSize();
1192
1193 if (num_breakpoints == 0) {
1194 result.AppendMessage("No breakpoints currently set.");
1195 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1196 return true;
1197 }
1198
1199 Stream &output_stream = result.GetOutputStream();
1200
Zachary Turner11eb9c62016-10-05 20:03:37 +00001201 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001202 // No breakpoint selected; show info about all currently set breakpoints.
1203 result.AppendMessage("Current breakpoints:");
1204 for (size_t i = 0; i < num_breakpoints; ++i) {
1205 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001206 if (breakpoint->AllowList())
1207 AddBreakpointDescription(&output_stream, breakpoint,
1208 m_options.m_level);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001209 }
1210 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1211 } else {
1212 // Particular breakpoints selected; show info about that breakpoint.
1213 BreakpointIDList valid_bp_ids;
1214 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001215 command, &target, result, &valid_bp_ids,
Jim Inghamb842f2e2017-09-14 20:22:49 +00001216 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001217
1218 if (result.Succeeded()) {
1219 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1220 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1221 Breakpoint *breakpoint =
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001222 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001223 AddBreakpointDescription(&output_stream, breakpoint,
1224 m_options.m_level);
1225 }
1226 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1227 } else {
1228 result.AppendError("Invalid breakpoint ID.");
1229 result.SetStatus(eReturnStatusFailed);
1230 }
1231 }
1232
1233 return result.Succeeded();
1234 }
1235
Jim Ingham5a988412012-06-08 21:56:10 +00001236private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001237 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001238};
1239
Jim Ingham5a988412012-06-08 21:56:10 +00001240// CommandObjectBreakpointClear
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001241#pragma mark Clear::CommandOptions
1242
Raphael Isemannf94668e2019-07-22 10:02:09 +00001243#define LLDB_OPTIONS_breakpoint_clear
1244#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001245
Jim Ingham5a988412012-06-08 21:56:10 +00001246#pragma mark Clear
1247
Kate Stoneb9c1b512016-09-06 20:57:50 +00001248class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001249public:
Fangrui Songefe8e7e2019-05-14 08:55:50 +00001250 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
Jim Ingham5a988412012-06-08 21:56:10 +00001251
Kate Stoneb9c1b512016-09-06 20:57:50 +00001252 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1253 : CommandObjectParsed(interpreter, "breakpoint clear",
1254 "Delete or disable breakpoints matching the "
1255 "specified source file and line.",
1256 "breakpoint clear <cmd-options>"),
1257 m_options() {}
1258
1259 ~CommandObjectBreakpointClear() override = default;
1260
1261 Options *GetOptions() override { return &m_options; }
1262
1263 class CommandOptions : public Options {
1264 public:
1265 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1266
1267 ~CommandOptions() override = default;
1268
Zachary Turner97206d52017-05-12 04:51:55 +00001269 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1270 ExecutionContext *execution_context) override {
1271 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001272 const int short_option = m_getopt_table[option_idx].val;
1273
1274 switch (short_option) {
1275 case 'f':
1276 m_filename.assign(option_arg);
1277 break;
1278
1279 case 'l':
Zachary Turnerfe114832016-11-12 16:56:47 +00001280 option_arg.getAsInteger(0, m_line_num);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001281 break;
1282
1283 default:
Raphael Isemann36162012019-08-22 08:08:05 +00001284 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +00001285 }
1286
1287 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001288 }
1289
Kate Stoneb9c1b512016-09-06 20:57:50 +00001290 void OptionParsingStarting(ExecutionContext *execution_context) override {
1291 m_filename.clear();
1292 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001293 }
1294
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001295 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001296 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001297 }
Jim Ingham5a988412012-06-08 21:56:10 +00001298
Kate Stoneb9c1b512016-09-06 20:57:50 +00001299 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001300
Kate Stoneb9c1b512016-09-06 20:57:50 +00001301 std::string m_filename;
1302 uint32_t m_line_num;
1303 };
Jim Ingham5a988412012-06-08 21:56:10 +00001304
1305protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001306 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001307 Target &target = GetSelectedOrDummyTarget();
Jim Ingham5a988412012-06-08 21:56:10 +00001308
Adrian Prantl05097242018-04-30 16:49:04 +00001309 // The following are the various types of breakpoints that could be
1310 // cleared:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001311 // 1). -f -l (clearing breakpoint by source location)
1312
1313 BreakpointClearType break_type = eClearTypeInvalid;
1314
1315 if (m_options.m_line_num != 0)
1316 break_type = eClearTypeFileAndLine;
1317
1318 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001319 target.GetBreakpointList().GetListMutex(lock);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001320
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001321 BreakpointList &breakpoints = target.GetBreakpointList();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001322 size_t num_breakpoints = breakpoints.GetSize();
1323
1324 // Early return if there's no breakpoint at all.
1325 if (num_breakpoints == 0) {
1326 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1327 result.SetStatus(eReturnStatusFailed);
1328 return result.Succeeded();
1329 }
1330
1331 // Find matching breakpoints and delete them.
1332
1333 // First create a copy of all the IDs.
1334 std::vector<break_id_t> BreakIDs;
1335 for (size_t i = 0; i < num_breakpoints; ++i)
1336 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1337
1338 int num_cleared = 0;
1339 StreamString ss;
1340 switch (break_type) {
1341 case eClearTypeFileAndLine: // Breakpoint by source position
1342 {
1343 const ConstString filename(m_options.m_filename.c_str());
1344 BreakpointLocationCollection loc_coll;
1345
1346 for (size_t i = 0; i < num_breakpoints; ++i) {
1347 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1348
1349 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1350 // If the collection size is 0, it's a full match and we can just
1351 // remove the breakpoint.
1352 if (loc_coll.GetSize() == 0) {
1353 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1354 ss.EOL();
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001355 target.RemoveBreakpointByID(bp->GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001356 ++num_cleared;
1357 }
1358 }
1359 }
1360 } break;
1361
1362 default:
1363 break;
1364 }
1365
1366 if (num_cleared > 0) {
1367 Stream &output_stream = result.GetOutputStream();
1368 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
Zachary Turnerc1564272016-11-16 21:15:24 +00001369 output_stream << ss.GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001370 output_stream.EOL();
1371 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1372 } else {
1373 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1374 result.SetStatus(eReturnStatusFailed);
1375 }
1376
1377 return result.Succeeded();
1378 }
1379
Jim Ingham5a988412012-06-08 21:56:10 +00001380private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001381 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001382};
1383
Jim Ingham5a988412012-06-08 21:56:10 +00001384// CommandObjectBreakpointDelete
Raphael Isemannf94668e2019-07-22 10:02:09 +00001385#define LLDB_OPTIONS_breakpoint_delete
1386#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001387
Jim Ingham5a988412012-06-08 21:56:10 +00001388#pragma mark Delete
1389
Kate Stoneb9c1b512016-09-06 20:57:50 +00001390class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001391public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001392 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1393 : CommandObjectParsed(interpreter, "breakpoint delete",
1394 "Delete the specified breakpoint(s). If no "
1395 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001396 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001397 m_options() {
1398 CommandArgumentEntry arg;
1399 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1400 eArgTypeBreakpointIDRange);
1401 // Add the entry for the first argument for this command to the object's
1402 // arguments vector.
1403 m_arguments.push_back(arg);
1404 }
1405
1406 ~CommandObjectBreakpointDelete() override = default;
1407
1408 Options *GetOptions() override { return &m_options; }
1409
1410 class CommandOptions : public Options {
1411 public:
1412 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1413
1414 ~CommandOptions() override = default;
1415
Zachary Turner97206d52017-05-12 04:51:55 +00001416 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1417 ExecutionContext *execution_context) override {
1418 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001419 const int short_option = m_getopt_table[option_idx].val;
1420
1421 switch (short_option) {
1422 case 'f':
1423 m_force = true;
1424 break;
1425
1426 case 'D':
1427 m_use_dummy = true;
1428 break;
1429
1430 default:
Raphael Isemann36162012019-08-22 08:08:05 +00001431 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +00001432 }
1433
1434 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001435 }
1436
Kate Stoneb9c1b512016-09-06 20:57:50 +00001437 void OptionParsingStarting(ExecutionContext *execution_context) override {
1438 m_use_dummy = false;
1439 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001440 }
1441
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001442 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001443 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001444 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001445
Kate Stoneb9c1b512016-09-06 20:57:50 +00001446 // Instance variables to hold the values for command options.
1447 bool m_use_dummy;
1448 bool m_force;
1449 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001450
Jim Ingham5a988412012-06-08 21:56:10 +00001451protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001452 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001453 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001454
Kate Stoneb9c1b512016-09-06 20:57:50 +00001455 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001456 target.GetBreakpointList().GetListMutex(lock);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001457
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001458 const BreakpointList &breakpoints = target.GetBreakpointList();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001459
1460 size_t num_breakpoints = breakpoints.GetSize();
1461
1462 if (num_breakpoints == 0) {
1463 result.AppendError("No breakpoints exist to be deleted.");
1464 result.SetStatus(eReturnStatusFailed);
1465 return false;
1466 }
1467
Zachary Turner11eb9c62016-10-05 20:03:37 +00001468 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001469 if (!m_options.m_force &&
1470 !m_interpreter.Confirm(
1471 "About to delete all breakpoints, do you want to do that?",
1472 true)) {
1473 result.AppendMessage("Operation cancelled...");
1474 } else {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001475 target.RemoveAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001476 result.AppendMessageWithFormat(
1477 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1478 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1479 }
1480 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1481 } else {
1482 // Particular breakpoint selected; disable that breakpoint.
1483 BreakpointIDList valid_bp_ids;
1484 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001485 command, &target, result, &valid_bp_ids,
Jim Inghamb842f2e2017-09-14 20:22:49 +00001486 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001487
1488 if (result.Succeeded()) {
1489 int delete_count = 0;
1490 int disable_count = 0;
1491 const size_t count = valid_bp_ids.GetSize();
1492 for (size_t i = 0; i < count; ++i) {
1493 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1494
1495 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1496 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1497 Breakpoint *breakpoint =
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001498 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001499 BreakpointLocation *location =
1500 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1501 // It makes no sense to try to delete individual locations, so we
1502 // disable them instead.
1503 if (location) {
1504 location->SetEnabled(false);
1505 ++disable_count;
1506 }
1507 } else {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001508 target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001509 ++delete_count;
1510 }
1511 }
1512 }
1513 result.AppendMessageWithFormat(
1514 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1515 delete_count, disable_count);
1516 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1517 }
1518 }
1519 return result.Succeeded();
1520 }
1521
Jim Ingham33df7cd2014-12-06 01:28:03 +00001522private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001523 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001524};
1525
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001526// CommandObjectBreakpointName
Raphael Isemannf94668e2019-07-22 10:02:09 +00001527#define LLDB_OPTIONS_breakpoint_name
1528#include "CommandOptions.inc"
Raphael Isemannbd68a052019-07-28 06:24:07 +00001529
Kate Stoneb9c1b512016-09-06 20:57:50 +00001530class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001531public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001532 BreakpointNameOptionGroup()
1533 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1534 }
1535
1536 ~BreakpointNameOptionGroup() override = default;
1537
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001538 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001539 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001540 }
1541
Zachary Turner97206d52017-05-12 04:51:55 +00001542 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1543 ExecutionContext *execution_context) override {
1544 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001545 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1546
1547 switch (short_option) {
1548 case 'N':
Zachary Turnerfe114832016-11-12 16:56:47 +00001549 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001550 error.Success())
Zachary Turnerfe114832016-11-12 16:56:47 +00001551 m_name.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001552 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001553 case 'B':
Zachary Turnerfe114832016-11-12 16:56:47 +00001554 if (m_breakpoint.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001555 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001556 "unrecognized value \"%s\" for breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +00001557 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001558 break;
1559 case 'D':
Zachary Turnerfe114832016-11-12 16:56:47 +00001560 if (m_use_dummy.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001561 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001562 "unrecognized value \"%s\" for use-dummy",
Zachary Turnerfe114832016-11-12 16:56:47 +00001563 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001564 break;
Jim Inghame9632eb2017-09-15 00:52:35 +00001565 case 'H':
1566 m_help_string.SetValueFromString(option_arg);
1567 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001568
1569 default:
Raphael Isemann36162012019-08-22 08:08:05 +00001570 llvm_unreachable("Unimplemented option");
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001571 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001572 return error;
1573 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001574
Kate Stoneb9c1b512016-09-06 20:57:50 +00001575 void OptionParsingStarting(ExecutionContext *execution_context) override {
1576 m_name.Clear();
1577 m_breakpoint.Clear();
1578 m_use_dummy.Clear();
1579 m_use_dummy.SetDefaultValue(false);
Jim Inghame9632eb2017-09-15 00:52:35 +00001580 m_help_string.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001581 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001582
Kate Stoneb9c1b512016-09-06 20:57:50 +00001583 OptionValueString m_name;
1584 OptionValueUInt64 m_breakpoint;
1585 OptionValueBoolean m_use_dummy;
Jim Inghame9632eb2017-09-15 00:52:35 +00001586 OptionValueString m_help_string;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001587};
1588
Raphael Isemannf94668e2019-07-22 10:02:09 +00001589#define LLDB_OPTIONS_breakpoint_access
1590#include "CommandOptions.inc"
Jim Inghamb842f2e2017-09-14 20:22:49 +00001591
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001592class BreakpointAccessOptionGroup : public OptionGroup {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001593public:
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001594 BreakpointAccessOptionGroup() : OptionGroup() {}
1595
Jim Inghamb842f2e2017-09-14 20:22:49 +00001596 ~BreakpointAccessOptionGroup() override = default;
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001597
Jim Inghamb842f2e2017-09-14 20:22:49 +00001598 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1599 return llvm::makeArrayRef(g_breakpoint_access_options);
1600 }
1601 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1602 ExecutionContext *execution_context) override {
1603 Status error;
1604 const int short_option
1605 = g_breakpoint_access_options[option_idx].short_option;
1606
1607 switch (short_option) {
1608 case 'L': {
1609 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001610 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001611 if (success) {
1612 m_permissions.SetAllowList(value);
1613 } else
1614 error.SetErrorStringWithFormat(
1615 "invalid boolean value '%s' passed for -L option",
1616 option_arg.str().c_str());
1617 } break;
1618 case 'A': {
1619 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001620 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001621 if (success) {
1622 m_permissions.SetAllowDisable(value);
1623 } else
1624 error.SetErrorStringWithFormat(
1625 "invalid boolean value '%s' passed for -L option",
1626 option_arg.str().c_str());
1627 } break;
1628 case 'D': {
1629 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001630 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001631 if (success) {
1632 m_permissions.SetAllowDelete(value);
1633 } else
1634 error.SetErrorStringWithFormat(
1635 "invalid boolean value '%s' passed for -L option",
1636 option_arg.str().c_str());
1637 } break;
Raphael Isemann36162012019-08-22 08:08:05 +00001638 default:
1639 llvm_unreachable("Unimplemented option");
Jim Inghamb842f2e2017-09-14 20:22:49 +00001640 }
1641
1642 return error;
1643 }
1644
1645 void OptionParsingStarting(ExecutionContext *execution_context) override {
1646 }
1647
1648 const BreakpointName::Permissions &GetPermissions() const
1649 {
1650 return m_permissions;
1651 }
1652 BreakpointName::Permissions m_permissions;
1653};
1654
1655class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1656public:
1657 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1658 : CommandObjectParsed(
1659 interpreter, "configure", "Configure the options for the breakpoint"
1660 " name provided. "
1661 "If you provide a breakpoint id, the options will be copied from "
1662 "the breakpoint, otherwise only the options specified will be set "
1663 "on the name.",
1664 "breakpoint name configure <command-options> "
1665 "<breakpoint-name-list>"),
1666 m_bp_opts(), m_option_group() {
1667 // Create the first variant for the first (and only) argument for this
1668 // command.
1669 CommandArgumentEntry arg1;
1670 CommandArgumentData id_arg;
1671 id_arg.arg_type = eArgTypeBreakpointName;
1672 id_arg.arg_repetition = eArgRepeatOptional;
1673 arg1.push_back(id_arg);
1674 m_arguments.push_back(arg1);
1675
1676 m_option_group.Append(&m_bp_opts,
1677 LLDB_OPT_SET_ALL,
1678 LLDB_OPT_SET_1);
1679 m_option_group.Append(&m_access_options,
1680 LLDB_OPT_SET_ALL,
1681 LLDB_OPT_SET_ALL);
Jim Inghame9632eb2017-09-15 00:52:35 +00001682 m_option_group.Append(&m_bp_id,
1683 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1684 LLDB_OPT_SET_ALL);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001685 m_option_group.Finalize();
1686 }
1687
1688 ~CommandObjectBreakpointNameConfigure() override = default;
1689
1690 Options *GetOptions() override { return &m_option_group; }
1691
1692protected:
1693 bool DoExecute(Args &command, CommandReturnObject &result) override {
1694
1695 const size_t argc = command.GetArgumentCount();
1696 if (argc == 0) {
1697 result.AppendError("No names provided.");
1698 result.SetStatus(eReturnStatusFailed);
1699 return false;
1700 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00001701
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001702 Target &target = GetSelectedOrDummyTarget(false);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001703
1704 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001705 target.GetBreakpointList().GetListMutex(lock);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001706
1707 // Make a pass through first to see that all the names are legal.
1708 for (auto &entry : command.entries()) {
1709 Status error;
Raphael Isemann0d9a2012019-09-13 11:26:48 +00001710 if (!BreakpointID::StringIsBreakpointName(entry.ref(), error))
Jim Inghamb842f2e2017-09-14 20:22:49 +00001711 {
1712 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1713 entry.c_str(), error.AsCString());
1714 result.SetStatus(eReturnStatusFailed);
1715 return false;
1716 }
1717 }
Adrian Prantl05097242018-04-30 16:49:04 +00001718 // Now configure them, we already pre-checked the names so we don't need to
1719 // check the error:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001720 BreakpointSP bp_sp;
1721 if (m_bp_id.m_breakpoint.OptionWasSet())
1722 {
1723 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001724 bp_sp = target.GetBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001725 if (!bp_sp)
1726 {
1727 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1728 bp_id);
1729 result.SetStatus(eReturnStatusFailed);
1730 return false;
1731 }
1732 }
1733
1734 Status error;
1735 for (auto &entry : command.entries()) {
1736 ConstString name(entry.c_str());
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001737 BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001738 if (!bp_name)
1739 continue;
Jim Inghame9632eb2017-09-15 00:52:35 +00001740 if (m_bp_id.m_help_string.OptionWasSet())
1741 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1742
Jim Inghamb842f2e2017-09-14 20:22:49 +00001743 if (bp_sp)
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001744 target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(),
Jim Inghamb842f2e2017-09-14 20:22:49 +00001745 m_access_options.GetPermissions());
1746 else
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001747 target.ConfigureBreakpointName(*bp_name,
Jim Inghamb842f2e2017-09-14 20:22:49 +00001748 m_bp_opts.GetBreakpointOptions(),
1749 m_access_options.GetPermissions());
1750 }
1751 return true;
1752 }
1753
1754private:
1755 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1756 BreakpointOptionGroup m_bp_opts;
1757 BreakpointAccessOptionGroup m_access_options;
1758 OptionGroupOptions m_option_group;
1759};
1760
Kate Stoneb9c1b512016-09-06 20:57:50 +00001761class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001762public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001763 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1764 : CommandObjectParsed(
1765 interpreter, "add", "Add a name to the breakpoints provided.",
1766 "breakpoint name add <command-options> <breakpoint-id-list>"),
1767 m_name_options(), m_option_group() {
1768 // Create the first variant for the first (and only) argument for this
1769 // command.
1770 CommandArgumentEntry arg1;
1771 CommandArgumentData id_arg;
1772 id_arg.arg_type = eArgTypeBreakpointID;
1773 id_arg.arg_repetition = eArgRepeatOptional;
1774 arg1.push_back(id_arg);
1775 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001776
Kate Stoneb9c1b512016-09-06 20:57:50 +00001777 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1778 m_option_group.Finalize();
1779 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001780
Kate Stoneb9c1b512016-09-06 20:57:50 +00001781 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001782
Kate Stoneb9c1b512016-09-06 20:57:50 +00001783 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001784
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001785protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001786 bool DoExecute(Args &command, CommandReturnObject &result) override {
1787 if (!m_name_options.m_name.OptionWasSet()) {
1788 result.SetError("No name option provided.");
1789 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001790 }
1791
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001792 Target &target =
Kate Stoneb9c1b512016-09-06 20:57:50 +00001793 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1794
Kate Stoneb9c1b512016-09-06 20:57:50 +00001795 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001796 target.GetBreakpointList().GetListMutex(lock);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001797
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001798 const BreakpointList &breakpoints = target.GetBreakpointList();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001799
1800 size_t num_breakpoints = breakpoints.GetSize();
1801 if (num_breakpoints == 0) {
1802 result.SetError("No breakpoints, cannot add names.");
1803 result.SetStatus(eReturnStatusFailed);
1804 return false;
1805 }
1806
1807 // Particular breakpoint selected; disable that breakpoint.
1808 BreakpointIDList valid_bp_ids;
1809 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001810 command, &target, result, &valid_bp_ids,
Jim Inghamb842f2e2017-09-14 20:22:49 +00001811 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001812
1813 if (result.Succeeded()) {
1814 if (valid_bp_ids.GetSize() == 0) {
1815 result.SetError("No breakpoints specified, cannot add names.");
1816 result.SetStatus(eReturnStatusFailed);
1817 return false;
1818 }
1819 size_t num_valid_ids = valid_bp_ids.GetSize();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001820 const char *bp_name = m_name_options.m_name.GetCurrentValue();
1821 Status error; // This error reports illegal names, but we've already
1822 // checked that, so we don't need to check it again here.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001823 for (size_t index = 0; index < num_valid_ids; index++) {
1824 lldb::break_id_t bp_id =
1825 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1826 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001827 target.AddNameToBreakpoint(bp_sp, bp_name, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001828 }
1829 }
1830
1831 return true;
1832 }
1833
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001834private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001835 BreakpointNameOptionGroup m_name_options;
1836 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001837};
1838
Kate Stoneb9c1b512016-09-06 20:57:50 +00001839class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001840public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001841 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1842 : CommandObjectParsed(
1843 interpreter, "delete",
1844 "Delete a name from the breakpoints provided.",
1845 "breakpoint name delete <command-options> <breakpoint-id-list>"),
1846 m_name_options(), m_option_group() {
1847 // Create the first variant for the first (and only) argument for this
1848 // command.
1849 CommandArgumentEntry arg1;
1850 CommandArgumentData id_arg;
1851 id_arg.arg_type = eArgTypeBreakpointID;
1852 id_arg.arg_repetition = eArgRepeatOptional;
1853 arg1.push_back(id_arg);
1854 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001855
Kate Stoneb9c1b512016-09-06 20:57:50 +00001856 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1857 m_option_group.Finalize();
1858 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001859
Kate Stoneb9c1b512016-09-06 20:57:50 +00001860 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001861
Kate Stoneb9c1b512016-09-06 20:57:50 +00001862 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001863
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001864protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001865 bool DoExecute(Args &command, CommandReturnObject &result) override {
1866 if (!m_name_options.m_name.OptionWasSet()) {
1867 result.SetError("No name option provided.");
1868 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001869 }
1870
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001871 Target &target =
Kate Stoneb9c1b512016-09-06 20:57:50 +00001872 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1873
Kate Stoneb9c1b512016-09-06 20:57:50 +00001874 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001875 target.GetBreakpointList().GetListMutex(lock);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001876
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001877 const BreakpointList &breakpoints = target.GetBreakpointList();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001878
1879 size_t num_breakpoints = breakpoints.GetSize();
1880 if (num_breakpoints == 0) {
1881 result.SetError("No breakpoints, cannot delete names.");
1882 result.SetStatus(eReturnStatusFailed);
1883 return false;
1884 }
1885
1886 // Particular breakpoint selected; disable that breakpoint.
1887 BreakpointIDList valid_bp_ids;
1888 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001889 command, &target, result, &valid_bp_ids,
Jim Inghamb842f2e2017-09-14 20:22:49 +00001890 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001891
1892 if (result.Succeeded()) {
1893 if (valid_bp_ids.GetSize() == 0) {
1894 result.SetError("No breakpoints specified, cannot delete names.");
1895 result.SetStatus(eReturnStatusFailed);
1896 return false;
1897 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00001898 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001899 size_t num_valid_ids = valid_bp_ids.GetSize();
1900 for (size_t index = 0; index < num_valid_ids; index++) {
1901 lldb::break_id_t bp_id =
1902 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1903 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001904 target.RemoveNameFromBreakpoint(bp_sp, bp_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001905 }
1906 }
1907
1908 return true;
1909 }
1910
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001911private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001912 BreakpointNameOptionGroup m_name_options;
1913 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001914};
1915
Kate Stoneb9c1b512016-09-06 20:57:50 +00001916class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001917public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001918 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1919 : CommandObjectParsed(interpreter, "list",
Jim Inghamb842f2e2017-09-14 20:22:49 +00001920 "List either the names for a breakpoint or info "
1921 "about a given name. With no arguments, lists all "
1922 "names",
Kate Stoneb9c1b512016-09-06 20:57:50 +00001923 "breakpoint name list <command-options>"),
1924 m_name_options(), m_option_group() {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001925 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001926 m_option_group.Finalize();
1927 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001928
Kate Stoneb9c1b512016-09-06 20:57:50 +00001929 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001930
Kate Stoneb9c1b512016-09-06 20:57:50 +00001931 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001932
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001933protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001934 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001935 Target &target =
Kate Stoneb9c1b512016-09-06 20:57:50 +00001936 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001937
Jim Inghamb842f2e2017-09-14 20:22:49 +00001938 std::vector<std::string> name_list;
1939 if (command.empty()) {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001940 target.GetBreakpointNames(name_list);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001941 } else {
1942 for (const Args::ArgEntry &arg : command)
1943 {
1944 name_list.push_back(arg.c_str());
1945 }
1946 }
1947
1948 if (name_list.empty()) {
1949 result.AppendMessage("No breakpoint names found.");
1950 } else {
1951 for (const std::string &name_str : name_list) {
1952 const char *name = name_str.c_str();
1953 // First print out the options for the name:
1954 Status error;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001955 BreakpointName *bp_name =
1956 target.FindBreakpointName(ConstString(name), false, error);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001957 if (bp_name)
1958 {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001959 StreamString s;
Jim Inghamb842f2e2017-09-14 20:22:49 +00001960 result.AppendMessageWithFormat("Name: %s\n", name);
1961 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
1962 {
1963 result.AppendMessage(s.GetString());
1964 }
1965
1966 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001967 target.GetBreakpointList().GetListMutex(lock);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001968
Raphael Isemanncb2380c2019-08-26 18:12:44 +00001969 BreakpointList &breakpoints = target.GetBreakpointList();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001970 bool any_set = false;
1971 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1972 if (bp_sp->MatchesName(name)) {
1973 StreamString s;
1974 any_set = true;
1975 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1976 s.EOL();
1977 result.AppendMessage(s.GetString());
1978 }
1979 }
1980 if (!any_set)
1981 result.AppendMessage("No breakpoints using this name.");
1982 } else {
1983 result.AppendMessageWithFormat("Name: %s not found.\n", name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001984 }
1985 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001986 }
1987 return true;
1988 }
1989
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001990private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001991 BreakpointNameOptionGroup m_name_options;
1992 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001993};
1994
Jim Inghame14dc262016-09-12 23:10:56 +00001995// CommandObjectBreakpointName
Kate Stoneb9c1b512016-09-06 20:57:50 +00001996class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001997public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001998 CommandObjectBreakpointName(CommandInterpreter &interpreter)
1999 : CommandObjectMultiword(
2000 interpreter, "name", "Commands to manage name tags for breakpoints",
2001 "breakpoint name <subcommand> [<command-options>]") {
2002 CommandObjectSP add_command_object(
2003 new CommandObjectBreakpointNameAdd(interpreter));
2004 CommandObjectSP delete_command_object(
2005 new CommandObjectBreakpointNameDelete(interpreter));
2006 CommandObjectSP list_command_object(
2007 new CommandObjectBreakpointNameList(interpreter));
Jim Inghamb842f2e2017-09-14 20:22:49 +00002008 CommandObjectSP configure_command_object(
2009 new CommandObjectBreakpointNameConfigure(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002010
Kate Stoneb9c1b512016-09-06 20:57:50 +00002011 LoadSubCommand("add", add_command_object);
2012 LoadSubCommand("delete", delete_command_object);
2013 LoadSubCommand("list", list_command_object);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002014 LoadSubCommand("configure", configure_command_object);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002015 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002016
Kate Stoneb9c1b512016-09-06 20:57:50 +00002017 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002018};
2019
Jim Inghame14dc262016-09-12 23:10:56 +00002020// CommandObjectBreakpointRead
Jim Ingham3acdf382016-09-22 22:20:28 +00002021#pragma mark Read::CommandOptions
Raphael Isemannf94668e2019-07-22 10:02:09 +00002022#define LLDB_OPTIONS_breakpoint_read
2023#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002024
2025#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002026
2027class CommandObjectBreakpointRead : public CommandObjectParsed {
2028public:
2029 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2030 : CommandObjectParsed(interpreter, "breakpoint read",
2031 "Read and set the breakpoints previously saved to "
2032 "a file with \"breakpoint write\". ",
2033 nullptr),
2034 m_options() {
2035 CommandArgumentEntry arg;
2036 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2037 eArgTypeBreakpointIDRange);
2038 // Add the entry for the first argument for this command to the object's
2039 // arguments vector.
2040 m_arguments.push_back(arg);
2041 }
2042
2043 ~CommandObjectBreakpointRead() override = default;
2044
2045 Options *GetOptions() override { return &m_options; }
2046
2047 class CommandOptions : public Options {
2048 public:
2049 CommandOptions() : Options() {}
2050
2051 ~CommandOptions() override = default;
2052
Zachary Turner97206d52017-05-12 04:51:55 +00002053 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2054 ExecutionContext *execution_context) override {
2055 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002056 const int short_option = m_getopt_table[option_idx].val;
2057
2058 switch (short_option) {
2059 case 'f':
2060 m_filename.assign(option_arg);
2061 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002062 case 'N': {
Zachary Turner97206d52017-05-12 04:51:55 +00002063 Status name_error;
Jim Ingham3acdf382016-09-22 22:20:28 +00002064 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2065 name_error)) {
2066 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2067 name_error.AsCString());
2068 }
2069 m_names.push_back(option_arg);
2070 break;
2071 }
Jim Inghame14dc262016-09-12 23:10:56 +00002072 default:
Raphael Isemann36162012019-08-22 08:08:05 +00002073 llvm_unreachable("Unimplemented option");
Jim Inghame14dc262016-09-12 23:10:56 +00002074 }
2075
2076 return error;
2077 }
2078
2079 void OptionParsingStarting(ExecutionContext *execution_context) override {
2080 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002081 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002082 }
2083
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002084 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002085 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002086 }
Jim Inghame14dc262016-09-12 23:10:56 +00002087
2088 // Instance variables to hold the values for command options.
2089
2090 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002091 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002092 };
2093
2094protected:
2095 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00002096 Target &target = GetSelectedOrDummyTarget();
Jim Inghame14dc262016-09-12 23:10:56 +00002097
Jim Ingham3acdf382016-09-22 22:20:28 +00002098 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00002099 target.GetBreakpointList().GetListMutex(lock);
Jim Ingham3acdf382016-09-22 22:20:28 +00002100
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002101 FileSpec input_spec(m_options.m_filename);
2102 FileSystem::Instance().Resolve(input_spec);
Jim Ingham01f16662016-09-14 19:07:35 +00002103 BreakpointIDList new_bps;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00002104 Status error = target.CreateBreakpointsFromFile(input_spec,
2105 m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002106
Jim Inghame14dc262016-09-12 23:10:56 +00002107 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002108 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002109 result.SetStatus(eReturnStatusFailed);
2110 return false;
2111 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002112
2113 Stream &output_stream = result.GetOutputStream();
2114
2115 size_t num_breakpoints = new_bps.GetSize();
2116 if (num_breakpoints == 0) {
2117 result.AppendMessage("No breakpoints added.");
2118 } else {
2119 // No breakpoint selected; show info about all currently set breakpoints.
2120 result.AppendMessage("New breakpoints:");
2121 for (size_t i = 0; i < num_breakpoints; ++i) {
2122 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
Raphael Isemanncb2380c2019-08-26 18:12:44 +00002123 Breakpoint *bp = target.GetBreakpointList()
Jim Ingham3acdf382016-09-22 22:20:28 +00002124 .FindBreakpointByID(bp_id.GetBreakpointID())
2125 .get();
2126 if (bp)
2127 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2128 false);
2129 }
2130 }
Jim Inghame14dc262016-09-12 23:10:56 +00002131 return result.Succeeded();
2132 }
2133
2134private:
2135 CommandOptions m_options;
2136};
2137
Jim Inghame14dc262016-09-12 23:10:56 +00002138// CommandObjectBreakpointWrite
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002139#pragma mark Write::CommandOptions
Raphael Isemannf94668e2019-07-22 10:02:09 +00002140#define LLDB_OPTIONS_breakpoint_write
2141#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002142
2143#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002144class CommandObjectBreakpointWrite : public CommandObjectParsed {
2145public:
2146 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2147 : CommandObjectParsed(interpreter, "breakpoint write",
2148 "Write the breakpoints listed to a file that can "
2149 "be read in with \"breakpoint read\". "
2150 "If given no arguments, writes all breakpoints.",
2151 nullptr),
2152 m_options() {
2153 CommandArgumentEntry arg;
2154 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2155 eArgTypeBreakpointIDRange);
2156 // Add the entry for the first argument for this command to the object's
2157 // arguments vector.
2158 m_arguments.push_back(arg);
2159 }
2160
2161 ~CommandObjectBreakpointWrite() override = default;
2162
2163 Options *GetOptions() override { return &m_options; }
2164
2165 class CommandOptions : public Options {
2166 public:
2167 CommandOptions() : Options() {}
2168
2169 ~CommandOptions() override = default;
2170
Zachary Turner97206d52017-05-12 04:51:55 +00002171 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2172 ExecutionContext *execution_context) override {
2173 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002174 const int short_option = m_getopt_table[option_idx].val;
2175
2176 switch (short_option) {
2177 case 'f':
2178 m_filename.assign(option_arg);
2179 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002180 case 'a':
2181 m_append = true;
2182 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002183 default:
Raphael Isemann36162012019-08-22 08:08:05 +00002184 llvm_unreachable("Unimplemented option");
Jim Inghame14dc262016-09-12 23:10:56 +00002185 }
2186
2187 return error;
2188 }
2189
2190 void OptionParsingStarting(ExecutionContext *execution_context) override {
2191 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002192 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002193 }
2194
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002195 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002196 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002197 }
Jim Inghame14dc262016-09-12 23:10:56 +00002198
2199 // Instance variables to hold the values for command options.
2200
2201 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002202 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002203 };
2204
2205protected:
2206 bool DoExecute(Args &command, CommandReturnObject &result) override {
Raphael Isemanncb2380c2019-08-26 18:12:44 +00002207 Target &target = GetSelectedOrDummyTarget();
Jim Inghame14dc262016-09-12 23:10:56 +00002208
Jim Inghame14dc262016-09-12 23:10:56 +00002209 std::unique_lock<std::recursive_mutex> lock;
Raphael Isemanncb2380c2019-08-26 18:12:44 +00002210 target.GetBreakpointList().GetListMutex(lock);
Jim Inghame14dc262016-09-12 23:10:56 +00002211
Jim Ingham01f16662016-09-14 19:07:35 +00002212 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002213 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002214 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Raphael Isemanncb2380c2019-08-26 18:12:44 +00002215 command, &target, result, &valid_bp_ids,
Jim Inghamb842f2e2017-09-14 20:22:49 +00002216 BreakpointName::Permissions::PermissionKinds::listPerm);
Jim Inghame14dc262016-09-12 23:10:56 +00002217
Jim Ingham01f16662016-09-14 19:07:35 +00002218 if (!result.Succeeded()) {
2219 result.SetStatus(eReturnStatusFailed);
2220 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002221 }
2222 }
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002223 FileSpec file_spec(m_options.m_filename);
2224 FileSystem::Instance().Resolve(file_spec);
Raphael Isemanncb2380c2019-08-26 18:12:44 +00002225 Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2226 m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002227 if (!error.Success()) {
2228 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2229 error.AsCString());
2230 result.SetStatus(eReturnStatusFailed);
2231 }
Jim Inghame14dc262016-09-12 23:10:56 +00002232 return result.Succeeded();
2233 }
2234
2235private:
2236 CommandOptions m_options;
2237};
2238
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002239// CommandObjectMultiwordBreakpoint
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002240#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002241
Kate Stoneb9c1b512016-09-06 20:57:50 +00002242CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2243 CommandInterpreter &interpreter)
2244 : CommandObjectMultiword(
2245 interpreter, "breakpoint",
2246 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2247 "breakpoint <subcommand> [<command-options>]") {
2248 CommandObjectSP list_command_object(
2249 new CommandObjectBreakpointList(interpreter));
2250 CommandObjectSP enable_command_object(
2251 new CommandObjectBreakpointEnable(interpreter));
2252 CommandObjectSP disable_command_object(
2253 new CommandObjectBreakpointDisable(interpreter));
2254 CommandObjectSP clear_command_object(
2255 new CommandObjectBreakpointClear(interpreter));
2256 CommandObjectSP delete_command_object(
2257 new CommandObjectBreakpointDelete(interpreter));
2258 CommandObjectSP set_command_object(
2259 new CommandObjectBreakpointSet(interpreter));
2260 CommandObjectSP command_command_object(
2261 new CommandObjectBreakpointCommand(interpreter));
2262 CommandObjectSP modify_command_object(
2263 new CommandObjectBreakpointModify(interpreter));
2264 CommandObjectSP name_command_object(
2265 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002266 CommandObjectSP write_command_object(
2267 new CommandObjectBreakpointWrite(interpreter));
2268 CommandObjectSP read_command_object(
2269 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002270
Kate Stoneb9c1b512016-09-06 20:57:50 +00002271 list_command_object->SetCommandName("breakpoint list");
2272 enable_command_object->SetCommandName("breakpoint enable");
2273 disable_command_object->SetCommandName("breakpoint disable");
2274 clear_command_object->SetCommandName("breakpoint clear");
2275 delete_command_object->SetCommandName("breakpoint delete");
2276 set_command_object->SetCommandName("breakpoint set");
2277 command_command_object->SetCommandName("breakpoint command");
2278 modify_command_object->SetCommandName("breakpoint modify");
2279 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002280 write_command_object->SetCommandName("breakpoint write");
2281 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002282
Kate Stoneb9c1b512016-09-06 20:57:50 +00002283 LoadSubCommand("list", list_command_object);
2284 LoadSubCommand("enable", enable_command_object);
2285 LoadSubCommand("disable", disable_command_object);
2286 LoadSubCommand("clear", clear_command_object);
2287 LoadSubCommand("delete", delete_command_object);
2288 LoadSubCommand("set", set_command_object);
2289 LoadSubCommand("command", command_command_object);
2290 LoadSubCommand("modify", modify_command_object);
2291 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002292 LoadSubCommand("write", write_command_object);
2293 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002294}
2295
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002296CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002297
Kate Stoneb9c1b512016-09-06 20:57:50 +00002298void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2299 bool allow_locations,
2300 CommandReturnObject &result,
Jim Inghamb842f2e2017-09-14 20:22:49 +00002301 BreakpointIDList *valid_ids,
2302 BreakpointName::Permissions
2303 ::PermissionKinds
2304 purpose) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002305 // args can be strings representing 1). integers (for breakpoint ids)
2306 // 2). the full breakpoint & location
2307 // canonical representation
2308 // 3). the word "to" or a hyphen,
2309 // representing a range (in which case there
2310 // had *better* be an entry both before &
2311 // after of one of the first two types.
2312 // 4). A breakpoint name
2313 // If args is empty, we will use the last created breakpoint (if there is
2314 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002315
Kate Stoneb9c1b512016-09-06 20:57:50 +00002316 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002317
Zachary Turner11eb9c62016-10-05 20:03:37 +00002318 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002319 if (target->GetLastCreatedBreakpoint()) {
2320 valid_ids->AddBreakpointID(BreakpointID(
2321 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2322 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2323 } else {
2324 result.AppendError(
2325 "No breakpoint specified and no last created breakpoint.");
2326 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002327 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002328 return;
2329 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002330
Kate Stoneb9c1b512016-09-06 20:57:50 +00002331 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
Adrian Prantl05097242018-04-30 16:49:04 +00002332 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2333 // id range strings over; instead generate a list of strings for all the
2334 // breakpoint ids in the range, and shove all of those breakpoint id strings
2335 // into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002336
Jim Inghamb842f2e2017-09-14 20:22:49 +00002337 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2338 purpose, result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002339
Kate Stoneb9c1b512016-09-06 20:57:50 +00002340 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2341 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002342
Pavel Labath16662f32018-06-20 08:12:50 +00002343 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002344
Adrian Prantl05097242018-04-30 16:49:04 +00002345 // At this point, all of the breakpoint ids that the user passed in have
2346 // been converted to breakpoint IDs and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002347
Kate Stoneb9c1b512016-09-06 20:57:50 +00002348 if (result.Succeeded()) {
2349 // Now that we've converted everything from args into a list of breakpoint
Adrian Prantl05097242018-04-30 16:49:04 +00002350 // ids, go through our tentative list of breakpoint id's and verify that
2351 // they correspond to valid/currently set breakpoints.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002352
2353 const size_t count = valid_ids->GetSize();
2354 for (size_t i = 0; i < count; ++i) {
2355 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2356 Breakpoint *breakpoint =
2357 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2358 if (breakpoint != nullptr) {
2359 const size_t num_locations = breakpoint->GetNumLocations();
2360 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2361 StreamString id_str;
2362 BreakpointID::GetCanonicalReference(
2363 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2364 i = valid_ids->GetSize() + 1;
2365 result.AppendErrorWithFormat(
2366 "'%s' is not a currently valid breakpoint/location id.\n",
2367 id_str.GetData());
2368 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002369 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002370 } else {
2371 i = valid_ids->GetSize() + 1;
2372 result.AppendErrorWithFormat(
2373 "'%d' is not a currently valid breakpoint ID.\n",
2374 cur_bp_id.GetBreakpointID());
2375 result.SetStatus(eReturnStatusFailed);
2376 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002377 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002378 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002379}