blob: bd38e0edf2e913a7be0c428271eb57e08e159cb5 [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
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +000047static constexpr OptionDefinition g_breakpoint_modify_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +000048#define LLDB_OPTIONS_breakpoint_modify
49#include "CommandOptions.inc"
Jim Inghamb842f2e2017-09-14 20:22:49 +000050};
51class lldb_private::BreakpointOptionGroup : public OptionGroup
52{
53public:
54 BreakpointOptionGroup() :
55 OptionGroup(),
56 m_bp_opts(false) {}
57
58 ~BreakpointOptionGroup() override = default;
59
60 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
61 return llvm::makeArrayRef(g_breakpoint_modify_options);
62 }
63
64 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
65 ExecutionContext *execution_context) override {
66 Status error;
67 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
68
69 switch (short_option) {
70 case 'c':
Adrian Prantl05097242018-04-30 16:49:04 +000071 // Normally an empty breakpoint condition marks is as unset. But we need
72 // to say it was passed in.
Jim Inghamb842f2e2017-09-14 20:22:49 +000073 m_bp_opts.SetCondition(option_arg.str().c_str());
74 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
75 break;
76 case 'C':
77 m_commands.push_back(option_arg);
78 break;
79 case 'd':
80 m_bp_opts.SetEnabled(false);
81 break;
82 case 'e':
83 m_bp_opts.SetEnabled(true);
84 break;
85 case 'G': {
86 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +000087 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +000088 if (success) {
89 m_bp_opts.SetAutoContinue(value);
90 } else
91 error.SetErrorStringWithFormat(
92 "invalid boolean value '%s' passed for -G option",
93 option_arg.str().c_str());
94 }
95 break;
96 case 'i':
97 {
98 uint32_t ignore_count;
99 if (option_arg.getAsInteger(0, ignore_count))
100 error.SetErrorStringWithFormat("invalid ignore count '%s'",
101 option_arg.str().c_str());
102 else
103 m_bp_opts.SetIgnoreCount(ignore_count);
104 }
105 break;
106 case 'o': {
107 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000108 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000109 if (success) {
110 m_bp_opts.SetOneShot(value);
111 } else
112 error.SetErrorStringWithFormat(
113 "invalid boolean value '%s' passed for -o option",
114 option_arg.str().c_str());
115 } break;
116 case 't':
117 {
118 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
119 if (option_arg[0] != '\0') {
120 if (option_arg.getAsInteger(0, thread_id))
121 error.SetErrorStringWithFormat("invalid thread id string '%s'",
122 option_arg.str().c_str());
123 }
124 m_bp_opts.SetThreadID(thread_id);
125 }
126 break;
127 case 'T':
128 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
129 break;
130 case 'q':
131 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
132 break;
133 case 'x':
134 {
135 uint32_t thread_index = UINT32_MAX;
136 if (option_arg[0] != '\n') {
137 if (option_arg.getAsInteger(0, thread_index))
138 error.SetErrorStringWithFormat("invalid thread index string '%s'",
139 option_arg.str().c_str());
140 }
141 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
142 }
143 break;
144 default:
145 error.SetErrorStringWithFormat("unrecognized option '%c'",
146 short_option);
147 break;
148 }
149
150 return error;
151 }
152
153 void OptionParsingStarting(ExecutionContext *execution_context) override {
154 m_bp_opts.Clear();
155 m_commands.clear();
156 }
157
158 Status OptionParsingFinished(ExecutionContext *execution_context) override {
159 if (!m_commands.empty())
160 {
161 if (!m_commands.empty())
162 {
163 auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
164
165 for (std::string &str : m_commands)
166 cmd_data->user_source.AppendString(str);
167
168 cmd_data->stop_on_error = true;
169 m_bp_opts.SetCommandDataCallback(cmd_data);
170 }
171 }
172 return Status();
173 }
174
175 const BreakpointOptions &GetBreakpointOptions()
176 {
177 return m_bp_opts;
178 }
179
180 std::vector<std::string> m_commands;
181 BreakpointOptions m_bp_opts;
182
183};
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000184static constexpr OptionDefinition g_breakpoint_dummy_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +0000185#define LLDB_OPTIONS_breakpoint_dummy
186#include "CommandOptions.inc"
Jim Inghamb842f2e2017-09-14 20:22:49 +0000187};
188
189class BreakpointDummyOptionGroup : public OptionGroup
190{
191public:
192 BreakpointDummyOptionGroup() :
193 OptionGroup() {}
194
195 ~BreakpointDummyOptionGroup() override = default;
196
197 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
198 return llvm::makeArrayRef(g_breakpoint_dummy_options);
199 }
200
201 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
202 ExecutionContext *execution_context) override {
203 Status error;
204 const int short_option = g_breakpoint_modify_options[option_idx].short_option;
205
206 switch (short_option) {
207 case 'D':
208 m_use_dummy = true;
209 break;
210 default:
211 error.SetErrorStringWithFormat("unrecognized option '%c'",
212 short_option);
213 break;
214 }
215
216 return error;
217 }
218
219 void OptionParsingStarting(ExecutionContext *execution_context) override {
220 m_use_dummy = false;
221 }
222
223 bool m_use_dummy;
224
225};
226
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +0000227static constexpr OptionDefinition g_breakpoint_set_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +0000228#define LLDB_OPTIONS_breakpoint_set
229#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000230};
231
Jim Ingham5a988412012-06-08 21:56:10 +0000232// CommandObjectBreakpointSet
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233
Kate Stoneb9c1b512016-09-06 20:57:50 +0000234class CommandObjectBreakpointSet : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000235public:
Fangrui Songefe8e7e2019-05-14 08:55:50 +0000236 enum BreakpointSetType {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 eSetTypeInvalid,
238 eSetTypeFileAndLine,
239 eSetTypeAddress,
240 eSetTypeFunctionName,
241 eSetTypeFunctionRegexp,
242 eSetTypeSourceRegexp,
Jim Ingham3815e702018-09-13 21:35:32 +0000243 eSetTypeException,
244 eSetTypeScripted,
Fangrui Songefe8e7e2019-05-14 08:55:50 +0000245 };
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000246
Kate Stoneb9c1b512016-09-06 20:57:50 +0000247 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
248 : CommandObjectParsed(
249 interpreter, "breakpoint set",
250 "Sets a breakpoint or set of breakpoints in the executable.",
251 "breakpoint set <cmd-options>"),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000252 m_bp_opts(), m_options() {
253 // We're picking up all the normal options, commands and disable.
254 m_all_options.Append(&m_bp_opts,
255 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
256 LLDB_OPT_SET_ALL);
257 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
258 m_all_options.Append(&m_options);
259 m_all_options.Finalize();
260 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000261
262 ~CommandObjectBreakpointSet() override = default;
263
Jim Inghamb842f2e2017-09-14 20:22:49 +0000264 Options *GetOptions() override { return &m_all_options; }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265
Jim Inghamb842f2e2017-09-14 20:22:49 +0000266 class CommandOptions : public OptionGroup {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000267 public:
268 CommandOptions()
Jim Inghamb842f2e2017-09-14 20:22:49 +0000269 : OptionGroup(), m_condition(), m_filenames(), m_line_num(0), m_column(0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000270 m_func_names(), m_func_name_type_mask(eFunctionNameTypeNone),
271 m_func_regexp(), m_source_text_regexp(), m_modules(), m_load_addr(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272 m_catch_bp(false), m_throw_bp(true), m_hardware(false),
273 m_exception_language(eLanguageTypeUnknown),
274 m_language(lldb::eLanguageTypeUnknown),
Jim Inghamb842f2e2017-09-14 20:22:49 +0000275 m_skip_prologue(eLazyBoolCalculate),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000276 m_all_files(false), m_move_to_nearest_code(eLazyBoolCalculate) {}
277
278 ~CommandOptions() override = default;
279
Zachary Turner97206d52017-05-12 04:51:55 +0000280 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
281 ExecutionContext *execution_context) override {
282 Status error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000283 const int short_option = g_breakpoint_set_options[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284
285 switch (short_option) {
286 case 'a': {
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000287 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
288 LLDB_INVALID_ADDRESS, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 } break;
290
291 case 'A':
292 m_all_files = true;
293 break;
294
295 case 'b':
296 m_func_names.push_back(option_arg);
297 m_func_name_type_mask |= eFunctionNameTypeBase;
298 break;
299
Zachary Turnerfe114832016-11-12 16:56:47 +0000300 case 'C':
301 if (option_arg.getAsInteger(0, m_column))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000302 error.SetErrorStringWithFormat("invalid column number: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000303 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000304 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305
Kate Stoneb9c1b512016-09-06 20:57:50 +0000306 case 'E': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000307 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000308
309 switch (language) {
310 case eLanguageTypeC89:
311 case eLanguageTypeC:
312 case eLanguageTypeC99:
313 case eLanguageTypeC11:
314 m_exception_language = eLanguageTypeC;
315 break;
316 case eLanguageTypeC_plus_plus:
317 case eLanguageTypeC_plus_plus_03:
318 case eLanguageTypeC_plus_plus_11:
319 case eLanguageTypeC_plus_plus_14:
320 m_exception_language = eLanguageTypeC_plus_plus;
321 break;
322 case eLanguageTypeObjC:
323 m_exception_language = eLanguageTypeObjC;
324 break;
325 case eLanguageTypeObjC_plus_plus:
326 error.SetErrorStringWithFormat(
327 "Set exception breakpoints separately for c++ and objective-c");
328 break;
329 case eLanguageTypeUnknown:
330 error.SetErrorStringWithFormat(
331 "Unknown language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000332 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000333 break;
334 default:
335 error.SetErrorStringWithFormat(
336 "Unsupported language type: '%s' for exception breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +0000337 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000338 }
339 } break;
340
341 case 'f':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000342 m_filenames.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000343 break;
344
345 case 'F':
346 m_func_names.push_back(option_arg);
347 m_func_name_type_mask |= eFunctionNameTypeFull;
348 break;
Jim Inghamf08f5c92017-08-03 18:13:24 +0000349
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350 case 'h': {
351 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000352 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000353 if (!success)
354 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000355 "Invalid boolean value for on-catch option: '%s'",
356 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357 } break;
358
359 case 'H':
360 m_hardware = true;
361 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000362
363 case 'k': {
364 if (m_current_key.empty())
365 m_current_key.assign(option_arg);
366 else
367 error.SetErrorStringWithFormat("Key: %s missing value.",
368 m_current_key.c_str());
369
370 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000371 case 'K': {
372 bool success;
373 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000374 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375 if (value)
376 m_skip_prologue = eLazyBoolYes;
377 else
378 m_skip_prologue = eLazyBoolNo;
379
380 if (!success)
381 error.SetErrorStringWithFormat(
382 "Invalid boolean value for skip prologue option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000383 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000384 } break;
385
Zachary Turnerfe114832016-11-12 16:56:47 +0000386 case 'l':
387 if (option_arg.getAsInteger(0, m_line_num))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000388 error.SetErrorStringWithFormat("invalid line number: %s.",
Zachary Turnerfe114832016-11-12 16:56:47 +0000389 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000390 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000391
392 case 'L':
Zachary Turnerfe114832016-11-12 16:56:47 +0000393 m_language = Language::GetLanguageTypeFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000394 if (m_language == eLanguageTypeUnknown)
395 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000396 "Unknown language type: '%s' for breakpoint",
397 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000398 break;
399
400 case 'm': {
401 bool success;
402 bool value;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000403 value = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000404 if (value)
405 m_move_to_nearest_code = eLazyBoolYes;
406 else
407 m_move_to_nearest_code = eLazyBoolNo;
408
409 if (!success)
410 error.SetErrorStringWithFormat(
411 "Invalid boolean value for move-to-nearest-code option: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +0000412 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000413 break;
414 }
415
416 case 'M':
417 m_func_names.push_back(option_arg);
418 m_func_name_type_mask |= eFunctionNameTypeMethod;
419 break;
420
421 case 'n':
422 m_func_names.push_back(option_arg);
423 m_func_name_type_mask |= eFunctionNameTypeAuto;
424 break;
425
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000426 case 'N': {
Zachary Turnerfe114832016-11-12 16:56:47 +0000427 if (BreakpointID::StringIsBreakpointName(option_arg, error))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000428 m_breakpoint_names.push_back(option_arg);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000429 else
430 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
Zachary Turnerfe114832016-11-12 16:56:47 +0000431 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000432 break;
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000433 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000434
435 case 'R': {
436 lldb::addr_t tmp_offset_addr;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000437 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
438 option_arg, 0, &error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000439 if (error.Success())
440 m_offset_addr = tmp_offset_addr;
441 } break;
442
Kate Stoneb9c1b512016-09-06 20:57:50 +0000443 case 'O':
Zachary Turnerfe114832016-11-12 16:56:47 +0000444 m_exception_extra_args.AppendArgument("-O");
445 m_exception_extra_args.AppendArgument(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446 break;
447
448 case 'p':
449 m_source_text_regexp.assign(option_arg);
450 break;
Jim Ingham3815e702018-09-13 21:35:32 +0000451
452 case 'P':
453 m_python_class.assign(option_arg);
454 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000455
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456 case 'r':
457 m_func_regexp.assign(option_arg);
458 break;
459
460 case 's':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000461 m_modules.AppendIfUnique(FileSpec(option_arg));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462 break;
463
464 case 'S':
465 m_func_names.push_back(option_arg);
466 m_func_name_type_mask |= eFunctionNameTypeSelector;
467 break;
468
Jim Ingham3815e702018-09-13 21:35:32 +0000469 case 'v': {
470 if (!m_current_key.empty()) {
471 m_extra_args_sp->AddStringItem(m_current_key, option_arg);
472 m_current_key.clear();
473 }
474 else
475 error.SetErrorStringWithFormat("Value \"%s\" missing matching key.",
476 option_arg.str().c_str());
477 } break;
478
Kate Stoneb9c1b512016-09-06 20:57:50 +0000479 case 'w': {
480 bool success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +0000481 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482 if (!success)
483 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +0000484 "Invalid boolean value for on-throw option: '%s'",
485 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000486 } break;
487
Kate Stoneb9c1b512016-09-06 20:57:50 +0000488 case 'X':
489 m_source_regex_func_names.insert(option_arg);
490 break;
491
492 default:
493 error.SetErrorStringWithFormat("unrecognized option '%c'",
494 short_option);
495 break;
496 }
497
498 return error;
Jim Ingham5a988412012-06-08 21:56:10 +0000499 }
500
Kate Stoneb9c1b512016-09-06 20:57:50 +0000501 void OptionParsingStarting(ExecutionContext *execution_context) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000502 m_filenames.Clear();
503 m_line_num = 0;
504 m_column = 0;
505 m_func_names.clear();
506 m_func_name_type_mask = eFunctionNameTypeNone;
507 m_func_regexp.clear();
508 m_source_text_regexp.clear();
509 m_modules.Clear();
510 m_load_addr = LLDB_INVALID_ADDRESS;
511 m_offset_addr = 0;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000512 m_catch_bp = false;
513 m_throw_bp = true;
514 m_hardware = false;
515 m_exception_language = eLanguageTypeUnknown;
516 m_language = lldb::eLanguageTypeUnknown;
517 m_skip_prologue = eLazyBoolCalculate;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000518 m_breakpoint_names.clear();
519 m_all_files = false;
520 m_exception_extra_args.Clear();
521 m_move_to_nearest_code = eLazyBoolCalculate;
522 m_source_regex_func_names.clear();
Jim Ingham3815e702018-09-13 21:35:32 +0000523 m_python_class.clear();
Jonas Devlieghere796ac802019-02-11 23:13:08 +0000524 m_extra_args_sp = std::make_shared<StructuredData::Dictionary>();
Jim Ingham3815e702018-09-13 21:35:32 +0000525 m_current_key.clear();
Jim Ingham5a988412012-06-08 21:56:10 +0000526 }
527
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000528 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000529 return llvm::makeArrayRef(g_breakpoint_set_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000530 }
Jim Ingham5a988412012-06-08 21:56:10 +0000531
Kate Stoneb9c1b512016-09-06 20:57:50 +0000532 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +0000533
Kate Stoneb9c1b512016-09-06 20:57:50 +0000534 std::string m_condition;
535 FileSpecList m_filenames;
536 uint32_t m_line_num;
537 uint32_t m_column;
538 std::vector<std::string> m_func_names;
539 std::vector<std::string> m_breakpoint_names;
Zachary Turner117b1fa2018-10-25 20:45:40 +0000540 lldb::FunctionNameType m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000541 std::string m_func_regexp;
542 std::string m_source_text_regexp;
543 FileSpecList m_modules;
544 lldb::addr_t m_load_addr;
545 lldb::addr_t m_offset_addr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546 bool m_catch_bp;
547 bool m_throw_bp;
548 bool m_hardware; // Request to use hardware breakpoints
549 lldb::LanguageType m_exception_language;
550 lldb::LanguageType m_language;
551 LazyBool m_skip_prologue;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552 bool m_all_files;
553 Args m_exception_extra_args;
554 LazyBool m_move_to_nearest_code;
555 std::unordered_set<std::string> m_source_regex_func_names;
Jim Ingham3815e702018-09-13 21:35:32 +0000556 std::string m_python_class;
557 StructuredData::DictionarySP m_extra_args_sp;
558 std::string m_current_key;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000559 };
Jim Ingham5a988412012-06-08 21:56:10 +0000560
561protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000562 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000563 Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +0000564
Kate Stoneb9c1b512016-09-06 20:57:50 +0000565 if (target == nullptr) {
566 result.AppendError("Invalid target. Must set target before setting "
567 "breakpoints (see 'target create' command).");
568 result.SetStatus(eReturnStatusFailed);
569 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000570 }
571
Kate Stoneb9c1b512016-09-06 20:57:50 +0000572 // The following are the various types of breakpoints that could be set:
573 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
574 // 2). -a [-s -g] (setting breakpoint by address)
575 // 3). -n [-s -g] (setting breakpoint by function name)
576 // 4). -r [-s -g] (setting breakpoint by function name regular
577 // expression)
578 // 5). -p -f (setting a breakpoint by comparing a reg-exp
579 // to source text)
580 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
581 // given language.)
582
583 BreakpointSetType break_type = eSetTypeInvalid;
584
Jim Ingham3815e702018-09-13 21:35:32 +0000585 if (!m_options.m_python_class.empty())
586 break_type = eSetTypeScripted;
587 else if (m_options.m_line_num != 0)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000588 break_type = eSetTypeFileAndLine;
589 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
590 break_type = eSetTypeAddress;
591 else if (!m_options.m_func_names.empty())
592 break_type = eSetTypeFunctionName;
593 else if (!m_options.m_func_regexp.empty())
594 break_type = eSetTypeFunctionRegexp;
595 else if (!m_options.m_source_text_regexp.empty())
596 break_type = eSetTypeSourceRegexp;
597 else if (m_options.m_exception_language != eLanguageTypeUnknown)
598 break_type = eSetTypeException;
599
Jim Inghamb842f2e2017-09-14 20:22:49 +0000600 BreakpointSP bp_sp = nullptr;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000601 FileSpec module_spec;
602 const bool internal = false;
603
604 // If the user didn't specify skip-prologue, having an offset should turn
605 // that off.
606 if (m_options.m_offset_addr != 0 &&
607 m_options.m_skip_prologue == eLazyBoolCalculate)
608 m_options.m_skip_prologue = eLazyBoolNo;
609
610 switch (break_type) {
611 case eSetTypeFileAndLine: // Breakpoint by source position
612 {
613 FileSpec file;
614 const size_t num_files = m_options.m_filenames.GetSize();
615 if (num_files == 0) {
616 if (!GetDefaultFile(target, file, result)) {
617 result.AppendError("No file supplied and no default file available.");
618 result.SetStatus(eReturnStatusFailed);
619 return false;
620 }
621 } else if (num_files > 1) {
622 result.AppendError("Only one file at a time is allowed for file and "
623 "line breakpoints.");
624 result.SetStatus(eReturnStatusFailed);
625 return false;
626 } else
627 file = m_options.m_filenames.GetFileSpecAtIndex(0);
628
629 // Only check for inline functions if
630 LazyBool check_inlines = eLazyBoolCalculate;
631
Jim Inghamb842f2e2017-09-14 20:22:49 +0000632 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
633 file,
Adrian Prantl431b1582018-08-30 15:11:00 +0000634 m_options.m_line_num,
635 m_options.m_column,
Jim Inghamb842f2e2017-09-14 20:22:49 +0000636 m_options.m_offset_addr,
637 check_inlines,
638 m_options.m_skip_prologue,
639 internal,
640 m_options.m_hardware,
641 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000642 } break;
643
644 case eSetTypeAddress: // Breakpoint by address
645 {
646 // If a shared library has been specified, make an lldb_private::Address
Jim Inghamb842f2e2017-09-14 20:22:49 +0000647 // with the library, and use that. That way the address breakpoint
648 // will track the load location of the library.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000649 size_t num_modules_specified = m_options.m_modules.GetSize();
650 if (num_modules_specified == 1) {
651 const FileSpec *file_spec =
652 m_options.m_modules.GetFileSpecPointerAtIndex(0);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000653 bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr,
654 internal, file_spec,
655 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 } else if (num_modules_specified == 0) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000657 bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal,
658 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000659 } else {
660 result.AppendError("Only one shared library can be specified for "
661 "address breakpoints.");
662 result.SetStatus(eReturnStatusFailed);
663 return false;
664 }
665 break;
666 }
667 case eSetTypeFunctionName: // Breakpoint by function name
668 {
Zachary Turner117b1fa2018-10-25 20:45:40 +0000669 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000670
671 if (name_type_mask == 0)
672 name_type_mask = eFunctionNameTypeAuto;
673
Jim Inghamb842f2e2017-09-14 20:22:49 +0000674 bp_sp = target->CreateBreakpoint(&(m_options.m_modules),
675 &(m_options.m_filenames),
676 m_options.m_func_names,
677 name_type_mask,
678 m_options.m_language,
679 m_options.m_offset_addr,
680 m_options.m_skip_prologue,
681 internal,
682 m_options.m_hardware);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000683 } break;
684
685 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
686 // name
Jim Inghame14dc262016-09-12 23:10:56 +0000687 {
Zachary Turner95eae422016-09-21 16:01:28 +0000688 RegularExpression regexp(m_options.m_func_regexp);
Jim Inghame14dc262016-09-12 23:10:56 +0000689 if (!regexp.IsValid()) {
690 char err_str[1024];
691 regexp.GetErrorAsCString(err_str, sizeof(err_str));
692 result.AppendErrorWithFormat(
693 "Function name regular expression could not be compiled: \"%s\"",
694 err_str);
695 result.SetStatus(eReturnStatusFailed);
696 return false;
697 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000698
Jim Inghamb842f2e2017-09-14 20:22:49 +0000699 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules),
700 &(m_options.m_filenames),
701 regexp,
702 m_options.m_language,
703 m_options.m_skip_prologue,
704 internal,
705 m_options.m_hardware);
Jim Inghame14dc262016-09-12 23:10:56 +0000706 }
707 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000708 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
709 {
710 const size_t num_files = m_options.m_filenames.GetSize();
711
712 if (num_files == 0 && !m_options.m_all_files) {
713 FileSpec file;
714 if (!GetDefaultFile(target, file, result)) {
715 result.AppendError(
716 "No files provided and could not find default file.");
717 result.SetStatus(eReturnStatusFailed);
718 return false;
719 } else {
720 m_options.m_filenames.Append(file);
721 }
722 }
723
Zachary Turner95eae422016-09-21 16:01:28 +0000724 RegularExpression regexp(m_options.m_source_text_regexp);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000725 if (!regexp.IsValid()) {
726 char err_str[1024];
727 regexp.GetErrorAsCString(err_str, sizeof(err_str));
728 result.AppendErrorWithFormat(
729 "Source text regular expression could not be compiled: \"%s\"",
730 err_str);
731 result.SetStatus(eReturnStatusFailed);
732 return false;
733 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000734 bp_sp =
735 target->CreateSourceRegexBreakpoint(&(m_options.m_modules),
736 &(m_options.m_filenames),
737 m_options
738 .m_source_regex_func_names,
739 regexp,
740 internal,
741 m_options.m_hardware,
742 m_options.m_move_to_nearest_code);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000743 } break;
744 case eSetTypeException: {
Zachary Turner97206d52017-05-12 04:51:55 +0000745 Status precond_error;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000746 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language,
747 m_options.m_catch_bp,
748 m_options.m_throw_bp,
749 internal,
750 &m_options
751 .m_exception_extra_args,
752 &precond_error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000753 if (precond_error.Fail()) {
754 result.AppendErrorWithFormat(
755 "Error setting extra exception arguments: %s",
756 precond_error.AsCString());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000757 target->RemoveBreakpointByID(bp_sp->GetID());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000758 result.SetStatus(eReturnStatusFailed);
759 return false;
760 }
761 } break;
Jim Ingham3815e702018-09-13 21:35:32 +0000762 case eSetTypeScripted: {
763
764 Status error;
765 bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class,
766 &(m_options.m_modules),
767 &(m_options.m_filenames),
768 false,
769 m_options.m_hardware,
770 m_options.m_extra_args_sp,
771 &error);
772 if (error.Fail()) {
773 result.AppendErrorWithFormat(
774 "Error setting extra exception arguments: %s",
775 error.AsCString());
776 target->RemoveBreakpointByID(bp_sp->GetID());
777 result.SetStatus(eReturnStatusFailed);
778 return false;
779 }
780 } break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000781 default:
782 break;
783 }
784
785 // Now set the various options that were passed in:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000786 if (bp_sp) {
787 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000788
789 if (!m_options.m_breakpoint_names.empty()) {
Zachary Turner97206d52017-05-12 04:51:55 +0000790 Status name_error;
Jim Inghamff9a91e2016-09-21 01:21:19 +0000791 for (auto name : m_options.m_breakpoint_names) {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000792 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
Jim Inghamff9a91e2016-09-21 01:21:19 +0000793 if (name_error.Fail()) {
794 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
795 name.c_str());
Jim Inghamb842f2e2017-09-14 20:22:49 +0000796 target->RemoveBreakpointByID(bp_sp->GetID());
Jim Inghamff9a91e2016-09-21 01:21:19 +0000797 result.SetStatus(eReturnStatusFailed);
798 return false;
799 }
800 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000801 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000802 }
Jim Inghamb842f2e2017-09-14 20:22:49 +0000803
804 if (bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000805 Stream &output_stream = result.GetOutputStream();
806 const bool show_locations = false;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000807 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000808 show_locations);
Jonas Devlieghere57179862019-04-27 06:19:42 +0000809 if (target == GetDebugger().GetDummyTarget())
Kate Stoneb9c1b512016-09-06 20:57:50 +0000810 output_stream.Printf("Breakpoint set in dummy target, will get copied "
811 "into future targets.\n");
812 else {
Adrian Prantl05097242018-04-30 16:49:04 +0000813 // Don't print out this warning for exception breakpoints. They can
814 // get set before the target is set, but we won't know how to actually
815 // set the breakpoint till we run.
Jim Inghamb842f2e2017-09-14 20:22:49 +0000816 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000817 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
818 "actual locations.\n");
819 }
820 }
821 result.SetStatus(eReturnStatusSuccessFinishResult);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000822 } else if (!bp_sp) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000823 result.AppendError("Breakpoint creation failed: No breakpoint created.");
824 result.SetStatus(eReturnStatusFailed);
825 }
826
827 return result.Succeeded();
828 }
829
Jim Ingham5a988412012-06-08 21:56:10 +0000830private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000831 bool GetDefaultFile(Target *target, FileSpec &file,
832 CommandReturnObject &result) {
833 uint32_t default_line;
Adrian Prantl05097242018-04-30 16:49:04 +0000834 // First use the Source Manager's default file. Then use the current stack
835 // frame's file.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000836 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) {
837 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
838 if (cur_frame == nullptr) {
839 result.AppendError(
840 "No selected frame to use to find the default file.");
841 result.SetStatus(eReturnStatusFailed);
842 return false;
843 } else if (!cur_frame->HasDebugInformation()) {
844 result.AppendError("Cannot use the selected frame to find the default "
845 "file, it has no debug info.");
846 result.SetStatus(eReturnStatusFailed);
847 return false;
848 } else {
849 const SymbolContext &sc =
850 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
851 if (sc.line_entry.file) {
852 file = sc.line_entry.file;
853 } else {
854 result.AppendError("Can't find the file for the selected frame to "
855 "use as the default file.");
856 result.SetStatus(eReturnStatusFailed);
857 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000858 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000859 }
Jim Ingham5a988412012-06-08 21:56:10 +0000860 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000861 return true;
862 }
863
Jim Inghamb842f2e2017-09-14 20:22:49 +0000864 BreakpointOptionGroup m_bp_opts;
865 BreakpointDummyOptionGroup m_dummy_options;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000866 CommandOptions m_options;
Jim Inghamb842f2e2017-09-14 20:22:49 +0000867 OptionGroupOptions m_all_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000868};
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000869
Jim Ingham5a988412012-06-08 21:56:10 +0000870// CommandObjectBreakpointModify
Jim Ingham5a988412012-06-08 21:56:10 +0000871#pragma mark Modify
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000872
Kate Stoneb9c1b512016-09-06 20:57:50 +0000873class CommandObjectBreakpointModify : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000874public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000875 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
876 : CommandObjectParsed(interpreter, "breakpoint modify",
877 "Modify the options on a breakpoint or set of "
878 "breakpoints in the executable. "
879 "If no breakpoint is specified, acts on the last "
880 "created breakpoint. "
881 "With the exception of -e, -d and -i, passing an "
882 "empty argument clears the modification.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +0000883 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000884 m_options() {
885 CommandArgumentEntry arg;
886 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
887 eArgTypeBreakpointIDRange);
888 // Add the entry for the first argument for this command to the object's
889 // arguments vector.
890 m_arguments.push_back(arg);
Jim Inghamb842f2e2017-09-14 20:22:49 +0000891
892 m_options.Append(&m_bp_opts,
893 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
894 LLDB_OPT_SET_ALL);
895 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
896 m_options.Finalize();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000897 }
898
899 ~CommandObjectBreakpointModify() override = default;
900
901 Options *GetOptions() override { return &m_options; }
902
Jim Ingham5a988412012-06-08 21:56:10 +0000903protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000904 bool DoExecute(Args &command, CommandReturnObject &result) override {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000905 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000906 if (target == nullptr) {
907 result.AppendError("Invalid target. No existing target or breakpoints.");
908 result.SetStatus(eReturnStatusFailed);
909 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000910 }
911
Kate Stoneb9c1b512016-09-06 20:57:50 +0000912 std::unique_lock<std::recursive_mutex> lock;
913 target->GetBreakpointList().GetListMutex(lock);
914
915 BreakpointIDList valid_bp_ids;
916
917 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +0000918 command, target, result, &valid_bp_ids,
919 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920
921 if (result.Succeeded()) {
922 const size_t count = valid_bp_ids.GetSize();
923 for (size_t i = 0; i < count; ++i) {
924 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
925
926 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
927 Breakpoint *bp =
928 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
929 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
930 BreakpointLocation *location =
931 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +0000932 if (location)
933 location->GetLocationOptions()
934 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000935 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +0000936 bp->GetOptions()
937 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000938 }
939 }
940 }
941 }
942
943 return result.Succeeded();
944 }
945
Jim Ingham5a988412012-06-08 21:56:10 +0000946private:
Jim Inghamb842f2e2017-09-14 20:22:49 +0000947 BreakpointOptionGroup m_bp_opts;
948 BreakpointDummyOptionGroup m_dummy_opts;
949 OptionGroupOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +0000950};
Johnny Chen7d49c9c2012-05-25 21:10:46 +0000951
Jim Ingham5a988412012-06-08 21:56:10 +0000952// CommandObjectBreakpointEnable
Jim Ingham5a988412012-06-08 21:56:10 +0000953#pragma mark Enable
954
Kate Stoneb9c1b512016-09-06 20:57:50 +0000955class CommandObjectBreakpointEnable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +0000956public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000957 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
958 : CommandObjectParsed(interpreter, "enable",
959 "Enable the specified disabled breakpoint(s). If "
960 "no breakpoints are specified, enable all of them.",
961 nullptr) {
962 CommandArgumentEntry arg;
963 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
964 eArgTypeBreakpointIDRange);
965 // Add the entry for the first argument for this command to the object's
966 // arguments vector.
967 m_arguments.push_back(arg);
968 }
Jim Ingham5a988412012-06-08 21:56:10 +0000969
Kate Stoneb9c1b512016-09-06 20:57:50 +0000970 ~CommandObjectBreakpointEnable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +0000971
972protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000973 bool DoExecute(Args &command, CommandReturnObject &result) override {
974 Target *target = GetSelectedOrDummyTarget();
975 if (target == nullptr) {
976 result.AppendError("Invalid target. No existing target or breakpoints.");
977 result.SetStatus(eReturnStatusFailed);
978 return false;
Jim Ingham5a988412012-06-08 21:56:10 +0000979 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000980
981 std::unique_lock<std::recursive_mutex> lock;
982 target->GetBreakpointList().GetListMutex(lock);
983
984 const BreakpointList &breakpoints = target->GetBreakpointList();
985
986 size_t num_breakpoints = breakpoints.GetSize();
987
988 if (num_breakpoints == 0) {
989 result.AppendError("No breakpoints exist to be enabled.");
990 result.SetStatus(eReturnStatusFailed);
991 return false;
992 }
993
Zachary Turner11eb9c62016-10-05 20:03:37 +0000994 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000995 // No breakpoint selected; enable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +0000996 target->EnableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000997 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
998 " breakpoints)\n",
999 (uint64_t)num_breakpoints);
1000 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1001 } else {
1002 // Particular breakpoint selected; enable that breakpoint.
1003 BreakpointIDList valid_bp_ids;
1004 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001005 command, target, result, &valid_bp_ids,
1006 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001007
1008 if (result.Succeeded()) {
1009 int enable_count = 0;
1010 int loc_count = 0;
1011 const size_t count = valid_bp_ids.GetSize();
1012 for (size_t i = 0; i < count; ++i) {
1013 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1014
1015 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1016 Breakpoint *breakpoint =
1017 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1018 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1019 BreakpointLocation *location =
1020 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1021 if (location) {
1022 location->SetEnabled(true);
1023 ++loc_count;
1024 }
1025 } else {
1026 breakpoint->SetEnabled(true);
1027 ++enable_count;
1028 }
1029 }
1030 }
1031 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
1032 enable_count + loc_count);
1033 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1034 }
1035 }
1036
1037 return result.Succeeded();
1038 }
Jim Ingham5a988412012-06-08 21:56:10 +00001039};
1040
Jim Ingham5a988412012-06-08 21:56:10 +00001041// CommandObjectBreakpointDisable
Jim Ingham5a988412012-06-08 21:56:10 +00001042#pragma mark Disable
1043
Kate Stoneb9c1b512016-09-06 20:57:50 +00001044class CommandObjectBreakpointDisable : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001045public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001046 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
1047 : CommandObjectParsed(
1048 interpreter, "breakpoint disable",
1049 "Disable the specified breakpoint(s) without deleting "
1050 "them. If none are specified, disable all "
1051 "breakpoints.",
1052 nullptr) {
1053 SetHelpLong(
1054 "Disable the specified breakpoint(s) without deleting them. \
Kate Stone7428a182016-07-14 22:03:10 +00001055If none are specified, disable all breakpoints."
Kate Stoneb9c1b512016-09-06 20:57:50 +00001056 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001057
Kate Stone7428a182016-07-14 22:03:10 +00001058)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001059 "Note: disabling a breakpoint will cause none of its locations to be hit \
Kate Stone7428a182016-07-14 22:03:10 +00001060regardless of whether individual locations are enabled or disabled. After the sequence:"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001061 R"(
Kate Stoneea671fb2015-07-14 05:48:36 +00001062
1063 (lldb) break disable 1
1064 (lldb) break enable 1.1
1065
1066execution will NOT stop at location 1.1. To achieve that, type:
1067
1068 (lldb) break disable 1.*
1069 (lldb) break enable 1.1
1070
Kate Stone7428a182016-07-14 22:03:10 +00001071)"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001072 "The first command disables all locations for breakpoint 1, \
Kate Stone7428a182016-07-14 22:03:10 +00001073the second re-enables the first location.");
1074
Kate Stoneb9c1b512016-09-06 20:57:50 +00001075 CommandArgumentEntry arg;
1076 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1077 eArgTypeBreakpointIDRange);
1078 // Add the entry for the first argument for this command to the object's
1079 // arguments vector.
1080 m_arguments.push_back(arg);
1081 }
Jim Ingham5a988412012-06-08 21:56:10 +00001082
Kate Stoneb9c1b512016-09-06 20:57:50 +00001083 ~CommandObjectBreakpointDisable() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001084
1085protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001086 bool DoExecute(Args &command, CommandReturnObject &result) override {
1087 Target *target = GetSelectedOrDummyTarget();
1088 if (target == nullptr) {
1089 result.AppendError("Invalid target. No existing target or breakpoints.");
1090 result.SetStatus(eReturnStatusFailed);
1091 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001092 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001093
1094 std::unique_lock<std::recursive_mutex> lock;
1095 target->GetBreakpointList().GetListMutex(lock);
1096
1097 const BreakpointList &breakpoints = target->GetBreakpointList();
1098 size_t num_breakpoints = breakpoints.GetSize();
1099
1100 if (num_breakpoints == 0) {
1101 result.AppendError("No breakpoints exist to be disabled.");
1102 result.SetStatus(eReturnStatusFailed);
1103 return false;
1104 }
1105
Zachary Turner11eb9c62016-10-05 20:03:37 +00001106 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001107 // No breakpoint selected; disable all currently set breakpoints.
Jim Inghamb842f2e2017-09-14 20:22:49 +00001108 target->DisableAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001109 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1110 " breakpoints)\n",
1111 (uint64_t)num_breakpoints);
1112 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1113 } else {
1114 // Particular breakpoint selected; disable that breakpoint.
1115 BreakpointIDList valid_bp_ids;
1116
1117 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001118 command, target, result, &valid_bp_ids,
1119 BreakpointName::Permissions::PermissionKinds::disablePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001120
1121 if (result.Succeeded()) {
1122 int disable_count = 0;
1123 int loc_count = 0;
1124 const size_t count = valid_bp_ids.GetSize();
1125 for (size_t i = 0; i < count; ++i) {
1126 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1127
1128 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1129 Breakpoint *breakpoint =
1130 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1131 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1132 BreakpointLocation *location =
1133 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1134 if (location) {
1135 location->SetEnabled(false);
1136 ++loc_count;
1137 }
1138 } else {
1139 breakpoint->SetEnabled(false);
1140 ++disable_count;
1141 }
1142 }
1143 }
1144 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1145 disable_count + loc_count);
1146 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1147 }
1148 }
1149
1150 return result.Succeeded();
1151 }
Jim Ingham5a988412012-06-08 21:56:10 +00001152};
1153
Jim Ingham5a988412012-06-08 21:56:10 +00001154// CommandObjectBreakpointList
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001155
1156#pragma mark List::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001157static constexpr OptionDefinition g_breakpoint_list_options[] = {
Raphael Isemann6f4fb4e2019-07-12 15:30:55 +00001158#define LLDB_OPTIONS_breakpoint_list
Raphael Isemannc5a2d742019-07-16 09:27:02 +00001159#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001160};
1161
Jim Ingham5a988412012-06-08 21:56:10 +00001162#pragma mark List
1163
Kate Stoneb9c1b512016-09-06 20:57:50 +00001164class CommandObjectBreakpointList : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001165public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001166 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1167 : CommandObjectParsed(
1168 interpreter, "breakpoint list",
1169 "List some or all breakpoints at configurable levels of detail.",
1170 nullptr),
1171 m_options() {
1172 CommandArgumentEntry arg;
1173 CommandArgumentData bp_id_arg;
Jim Ingham5a988412012-06-08 21:56:10 +00001174
Kate Stoneb9c1b512016-09-06 20:57:50 +00001175 // Define the first (and only) variant of this arg.
1176 bp_id_arg.arg_type = eArgTypeBreakpointID;
1177 bp_id_arg.arg_repetition = eArgRepeatOptional;
Jim Ingham5a988412012-06-08 21:56:10 +00001178
Kate Stoneb9c1b512016-09-06 20:57:50 +00001179 // There is only one variant this argument could be; put it into the
1180 // argument entry.
1181 arg.push_back(bp_id_arg);
Jim Ingham5a988412012-06-08 21:56:10 +00001182
Kate Stoneb9c1b512016-09-06 20:57:50 +00001183 // Push the data for the first argument into the m_arguments vector.
1184 m_arguments.push_back(arg);
1185 }
1186
1187 ~CommandObjectBreakpointList() override = default;
1188
1189 Options *GetOptions() override { return &m_options; }
1190
1191 class CommandOptions : public Options {
1192 public:
1193 CommandOptions()
1194 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) {
Jim Ingham5a988412012-06-08 21:56:10 +00001195 }
1196
Kate Stoneb9c1b512016-09-06 20:57:50 +00001197 ~CommandOptions() override = default;
Jim Ingham5a988412012-06-08 21:56:10 +00001198
Zachary Turner97206d52017-05-12 04:51:55 +00001199 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1200 ExecutionContext *execution_context) override {
1201 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001202 const int short_option = m_getopt_table[option_idx].val;
1203
1204 switch (short_option) {
1205 case 'b':
1206 m_level = lldb::eDescriptionLevelBrief;
1207 break;
1208 case 'D':
1209 m_use_dummy = true;
1210 break;
1211 case 'f':
1212 m_level = lldb::eDescriptionLevelFull;
1213 break;
1214 case 'v':
1215 m_level = lldb::eDescriptionLevelVerbose;
1216 break;
1217 case 'i':
1218 m_internal = true;
1219 break;
1220 default:
1221 error.SetErrorStringWithFormat("unrecognized option '%c'",
1222 short_option);
1223 break;
1224 }
1225
1226 return error;
Jim Ingham1b54c882010-06-16 02:00:15 +00001227 }
Jim Ingham5a988412012-06-08 21:56:10 +00001228
Kate Stoneb9c1b512016-09-06 20:57:50 +00001229 void OptionParsingStarting(ExecutionContext *execution_context) override {
1230 m_level = lldb::eDescriptionLevelFull;
1231 m_internal = false;
1232 m_use_dummy = false;
1233 }
Jim Ingham5a988412012-06-08 21:56:10 +00001234
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001235 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001236 return llvm::makeArrayRef(g_breakpoint_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001237 }
Jim Ingham5a988412012-06-08 21:56:10 +00001238
Kate Stoneb9c1b512016-09-06 20:57:50 +00001239 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001240
Kate Stoneb9c1b512016-09-06 20:57:50 +00001241 lldb::DescriptionLevel m_level;
Jim Ingham5a988412012-06-08 21:56:10 +00001242
Kate Stoneb9c1b512016-09-06 20:57:50 +00001243 bool m_internal;
1244 bool m_use_dummy;
1245 };
Jim Ingham5a988412012-06-08 21:56:10 +00001246
1247protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001248 bool DoExecute(Args &command, CommandReturnObject &result) override {
1249 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001250
Kate Stoneb9c1b512016-09-06 20:57:50 +00001251 if (target == nullptr) {
1252 result.AppendError("Invalid target. No current target or breakpoints.");
1253 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1254 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001255 }
1256
Kate Stoneb9c1b512016-09-06 20:57:50 +00001257 const BreakpointList &breakpoints =
1258 target->GetBreakpointList(m_options.m_internal);
1259 std::unique_lock<std::recursive_mutex> lock;
1260 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1261
1262 size_t num_breakpoints = breakpoints.GetSize();
1263
1264 if (num_breakpoints == 0) {
1265 result.AppendMessage("No breakpoints currently set.");
1266 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1267 return true;
1268 }
1269
1270 Stream &output_stream = result.GetOutputStream();
1271
Zachary Turner11eb9c62016-10-05 20:03:37 +00001272 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001273 // No breakpoint selected; show info about all currently set breakpoints.
1274 result.AppendMessage("Current breakpoints:");
1275 for (size_t i = 0; i < num_breakpoints; ++i) {
1276 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001277 if (breakpoint->AllowList())
1278 AddBreakpointDescription(&output_stream, breakpoint,
1279 m_options.m_level);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001280 }
1281 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1282 } else {
1283 // Particular breakpoints selected; show info about that breakpoint.
1284 BreakpointIDList valid_bp_ids;
1285 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001286 command, target, result, &valid_bp_ids,
1287 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001288
1289 if (result.Succeeded()) {
1290 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1291 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1292 Breakpoint *breakpoint =
1293 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1294 AddBreakpointDescription(&output_stream, breakpoint,
1295 m_options.m_level);
1296 }
1297 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1298 } else {
1299 result.AppendError("Invalid breakpoint ID.");
1300 result.SetStatus(eReturnStatusFailed);
1301 }
1302 }
1303
1304 return result.Succeeded();
1305 }
1306
Jim Ingham5a988412012-06-08 21:56:10 +00001307private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001308 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001309};
1310
Jim Ingham5a988412012-06-08 21:56:10 +00001311// CommandObjectBreakpointClear
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001312#pragma mark Clear::CommandOptions
1313
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001314static constexpr OptionDefinition g_breakpoint_clear_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +00001315#define LLDB_OPTIONS_breakpoint_clear
1316#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001317};
1318
Jim Ingham5a988412012-06-08 21:56:10 +00001319#pragma mark Clear
1320
Kate Stoneb9c1b512016-09-06 20:57:50 +00001321class CommandObjectBreakpointClear : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001322public:
Fangrui Songefe8e7e2019-05-14 08:55:50 +00001323 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
Jim Ingham5a988412012-06-08 21:56:10 +00001324
Kate Stoneb9c1b512016-09-06 20:57:50 +00001325 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1326 : CommandObjectParsed(interpreter, "breakpoint clear",
1327 "Delete or disable breakpoints matching the "
1328 "specified source file and line.",
1329 "breakpoint clear <cmd-options>"),
1330 m_options() {}
1331
1332 ~CommandObjectBreakpointClear() override = default;
1333
1334 Options *GetOptions() override { return &m_options; }
1335
1336 class CommandOptions : public Options {
1337 public:
1338 CommandOptions() : Options(), m_filename(), m_line_num(0) {}
1339
1340 ~CommandOptions() override = default;
1341
Zachary Turner97206d52017-05-12 04:51:55 +00001342 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1343 ExecutionContext *execution_context) override {
1344 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001345 const int short_option = m_getopt_table[option_idx].val;
1346
1347 switch (short_option) {
1348 case 'f':
1349 m_filename.assign(option_arg);
1350 break;
1351
1352 case 'l':
Zachary Turnerfe114832016-11-12 16:56:47 +00001353 option_arg.getAsInteger(0, m_line_num);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001354 break;
1355
1356 default:
1357 error.SetErrorStringWithFormat("unrecognized option '%c'",
1358 short_option);
1359 break;
1360 }
1361
1362 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001363 }
1364
Kate Stoneb9c1b512016-09-06 20:57:50 +00001365 void OptionParsingStarting(ExecutionContext *execution_context) override {
1366 m_filename.clear();
1367 m_line_num = 0;
Jim Ingham5a988412012-06-08 21:56:10 +00001368 }
1369
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001370 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001371 return llvm::makeArrayRef(g_breakpoint_clear_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001372 }
Jim Ingham5a988412012-06-08 21:56:10 +00001373
Kate Stoneb9c1b512016-09-06 20:57:50 +00001374 // Instance variables to hold the values for command options.
Jim Ingham5a988412012-06-08 21:56:10 +00001375
Kate Stoneb9c1b512016-09-06 20:57:50 +00001376 std::string m_filename;
1377 uint32_t m_line_num;
1378 };
Jim Ingham5a988412012-06-08 21:56:10 +00001379
1380protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001381 bool DoExecute(Args &command, CommandReturnObject &result) override {
1382 Target *target = GetSelectedOrDummyTarget();
1383 if (target == nullptr) {
1384 result.AppendError("Invalid target. No existing target or breakpoints.");
1385 result.SetStatus(eReturnStatusFailed);
1386 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001387 }
1388
Adrian Prantl05097242018-04-30 16:49:04 +00001389 // The following are the various types of breakpoints that could be
1390 // cleared:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001391 // 1). -f -l (clearing breakpoint by source location)
1392
1393 BreakpointClearType break_type = eClearTypeInvalid;
1394
1395 if (m_options.m_line_num != 0)
1396 break_type = eClearTypeFileAndLine;
1397
1398 std::unique_lock<std::recursive_mutex> lock;
1399 target->GetBreakpointList().GetListMutex(lock);
1400
1401 BreakpointList &breakpoints = target->GetBreakpointList();
1402 size_t num_breakpoints = breakpoints.GetSize();
1403
1404 // Early return if there's no breakpoint at all.
1405 if (num_breakpoints == 0) {
1406 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1407 result.SetStatus(eReturnStatusFailed);
1408 return result.Succeeded();
1409 }
1410
1411 // Find matching breakpoints and delete them.
1412
1413 // First create a copy of all the IDs.
1414 std::vector<break_id_t> BreakIDs;
1415 for (size_t i = 0; i < num_breakpoints; ++i)
1416 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1417
1418 int num_cleared = 0;
1419 StreamString ss;
1420 switch (break_type) {
1421 case eClearTypeFileAndLine: // Breakpoint by source position
1422 {
1423 const ConstString filename(m_options.m_filename.c_str());
1424 BreakpointLocationCollection loc_coll;
1425
1426 for (size_t i = 0; i < num_breakpoints; ++i) {
1427 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1428
1429 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1430 // If the collection size is 0, it's a full match and we can just
1431 // remove the breakpoint.
1432 if (loc_coll.GetSize() == 0) {
1433 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1434 ss.EOL();
1435 target->RemoveBreakpointByID(bp->GetID());
1436 ++num_cleared;
1437 }
1438 }
1439 }
1440 } break;
1441
1442 default:
1443 break;
1444 }
1445
1446 if (num_cleared > 0) {
1447 Stream &output_stream = result.GetOutputStream();
1448 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
Zachary Turnerc1564272016-11-16 21:15:24 +00001449 output_stream << ss.GetString();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001450 output_stream.EOL();
1451 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1452 } else {
1453 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1454 result.SetStatus(eReturnStatusFailed);
1455 }
1456
1457 return result.Succeeded();
1458 }
1459
Jim Ingham5a988412012-06-08 21:56:10 +00001460private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001461 CommandOptions m_options;
Jim Ingham5a988412012-06-08 21:56:10 +00001462};
1463
Jim Ingham5a988412012-06-08 21:56:10 +00001464// CommandObjectBreakpointDelete
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001465static constexpr OptionDefinition g_breakpoint_delete_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +00001466#define LLDB_OPTIONS_breakpoint_delete
1467#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001468};
1469
Jim Ingham5a988412012-06-08 21:56:10 +00001470#pragma mark Delete
1471
Kate Stoneb9c1b512016-09-06 20:57:50 +00001472class CommandObjectBreakpointDelete : public CommandObjectParsed {
Jim Ingham5a988412012-06-08 21:56:10 +00001473public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001474 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1475 : CommandObjectParsed(interpreter, "breakpoint delete",
1476 "Delete the specified breakpoint(s). If no "
1477 "breakpoints are specified, delete them all.",
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001478 nullptr),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001479 m_options() {
1480 CommandArgumentEntry arg;
1481 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
1482 eArgTypeBreakpointIDRange);
1483 // Add the entry for the first argument for this command to the object's
1484 // arguments vector.
1485 m_arguments.push_back(arg);
1486 }
1487
1488 ~CommandObjectBreakpointDelete() override = default;
1489
1490 Options *GetOptions() override { return &m_options; }
1491
1492 class CommandOptions : public Options {
1493 public:
1494 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {}
1495
1496 ~CommandOptions() override = default;
1497
Zachary Turner97206d52017-05-12 04:51:55 +00001498 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1499 ExecutionContext *execution_context) override {
1500 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001501 const int short_option = m_getopt_table[option_idx].val;
1502
1503 switch (short_option) {
1504 case 'f':
1505 m_force = true;
1506 break;
1507
1508 case 'D':
1509 m_use_dummy = true;
1510 break;
1511
1512 default:
1513 error.SetErrorStringWithFormat("unrecognized option '%c'",
1514 short_option);
1515 break;
1516 }
1517
1518 return error;
Jim Ingham5a988412012-06-08 21:56:10 +00001519 }
1520
Kate Stoneb9c1b512016-09-06 20:57:50 +00001521 void OptionParsingStarting(ExecutionContext *execution_context) override {
1522 m_use_dummy = false;
1523 m_force = false;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001524 }
1525
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001526 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001527 return llvm::makeArrayRef(g_breakpoint_delete_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001528 }
Jim Ingham33df7cd2014-12-06 01:28:03 +00001529
Kate Stoneb9c1b512016-09-06 20:57:50 +00001530 // Instance variables to hold the values for command options.
1531 bool m_use_dummy;
1532 bool m_force;
1533 };
Jim Ingham33df7cd2014-12-06 01:28:03 +00001534
Jim Ingham5a988412012-06-08 21:56:10 +00001535protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001536 bool DoExecute(Args &command, CommandReturnObject &result) override {
1537 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
Jim Ingham33df7cd2014-12-06 01:28:03 +00001538
Kate Stoneb9c1b512016-09-06 20:57:50 +00001539 if (target == nullptr) {
1540 result.AppendError("Invalid target. No existing target or breakpoints.");
1541 result.SetStatus(eReturnStatusFailed);
1542 return false;
Jim Ingham5a988412012-06-08 21:56:10 +00001543 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001544
Kate Stoneb9c1b512016-09-06 20:57:50 +00001545 std::unique_lock<std::recursive_mutex> lock;
1546 target->GetBreakpointList().GetListMutex(lock);
1547
1548 const BreakpointList &breakpoints = target->GetBreakpointList();
1549
1550 size_t num_breakpoints = breakpoints.GetSize();
1551
1552 if (num_breakpoints == 0) {
1553 result.AppendError("No breakpoints exist to be deleted.");
1554 result.SetStatus(eReturnStatusFailed);
1555 return false;
1556 }
1557
Zachary Turner11eb9c62016-10-05 20:03:37 +00001558 if (command.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001559 if (!m_options.m_force &&
1560 !m_interpreter.Confirm(
1561 "About to delete all breakpoints, do you want to do that?",
1562 true)) {
1563 result.AppendMessage("Operation cancelled...");
1564 } else {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001565 target->RemoveAllowedBreakpoints();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001566 result.AppendMessageWithFormat(
1567 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1568 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1569 }
1570 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1571 } else {
1572 // Particular breakpoint selected; disable that breakpoint.
1573 BreakpointIDList valid_bp_ids;
1574 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001575 command, target, result, &valid_bp_ids,
1576 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001577
1578 if (result.Succeeded()) {
1579 int delete_count = 0;
1580 int disable_count = 0;
1581 const size_t count = valid_bp_ids.GetSize();
1582 for (size_t i = 0; i < count; ++i) {
1583 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1584
1585 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1586 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1587 Breakpoint *breakpoint =
1588 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1589 BreakpointLocation *location =
1590 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1591 // It makes no sense to try to delete individual locations, so we
1592 // disable them instead.
1593 if (location) {
1594 location->SetEnabled(false);
1595 ++disable_count;
1596 }
1597 } else {
1598 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1599 ++delete_count;
1600 }
1601 }
1602 }
1603 result.AppendMessageWithFormat(
1604 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1605 delete_count, disable_count);
1606 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1607 }
1608 }
1609 return result.Succeeded();
1610 }
1611
Jim Ingham33df7cd2014-12-06 01:28:03 +00001612private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001613 CommandOptions m_options;
Jim Ingham33df7cd2014-12-06 01:28:03 +00001614};
1615
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001616// CommandObjectBreakpointName
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001617
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001618static constexpr OptionDefinition g_breakpoint_name_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +00001619#define LLDB_OPTIONS_breakpoint_name
1620#include "CommandOptions.inc"
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001621};
Kate Stoneb9c1b512016-09-06 20:57:50 +00001622class BreakpointNameOptionGroup : public OptionGroup {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001623public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001624 BreakpointNameOptionGroup()
1625 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {
1626 }
1627
1628 ~BreakpointNameOptionGroup() override = default;
1629
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001630 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001631 return llvm::makeArrayRef(g_breakpoint_name_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001632 }
1633
Zachary Turner97206d52017-05-12 04:51:55 +00001634 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1635 ExecutionContext *execution_context) override {
1636 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001637 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1638
1639 switch (short_option) {
1640 case 'N':
Zachary Turnerfe114832016-11-12 16:56:47 +00001641 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
Kate Stoneb9c1b512016-09-06 20:57:50 +00001642 error.Success())
Zachary Turnerfe114832016-11-12 16:56:47 +00001643 m_name.SetValueFromString(option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001644 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001645 case 'B':
Zachary Turnerfe114832016-11-12 16:56:47 +00001646 if (m_breakpoint.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001647 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001648 "unrecognized value \"%s\" for breakpoint",
Zachary Turnerfe114832016-11-12 16:56:47 +00001649 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001650 break;
1651 case 'D':
Zachary Turnerfe114832016-11-12 16:56:47 +00001652 if (m_use_dummy.SetValueFromString(option_arg).Fail())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001653 error.SetErrorStringWithFormat(
Zachary Turner8cef4b02016-09-23 17:48:13 +00001654 "unrecognized value \"%s\" for use-dummy",
Zachary Turnerfe114832016-11-12 16:56:47 +00001655 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001656 break;
Jim Inghame9632eb2017-09-15 00:52:35 +00001657 case 'H':
1658 m_help_string.SetValueFromString(option_arg);
1659 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001660
1661 default:
1662 error.SetErrorStringWithFormat("unrecognized short option '%c'",
1663 short_option);
1664 break;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001665 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001666 return error;
1667 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001668
Kate Stoneb9c1b512016-09-06 20:57:50 +00001669 void OptionParsingStarting(ExecutionContext *execution_context) override {
1670 m_name.Clear();
1671 m_breakpoint.Clear();
1672 m_use_dummy.Clear();
1673 m_use_dummy.SetDefaultValue(false);
Jim Inghame9632eb2017-09-15 00:52:35 +00001674 m_help_string.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001675 }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001676
Kate Stoneb9c1b512016-09-06 20:57:50 +00001677 OptionValueString m_name;
1678 OptionValueUInt64 m_breakpoint;
1679 OptionValueBoolean m_use_dummy;
Jim Inghame9632eb2017-09-15 00:52:35 +00001680 OptionValueString m_help_string;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001681};
1682
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001683static constexpr OptionDefinition g_breakpoint_access_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +00001684#define LLDB_OPTIONS_breakpoint_access
1685#include "CommandOptions.inc"
Jim Inghamb842f2e2017-09-14 20:22:49 +00001686};
1687
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001688class BreakpointAccessOptionGroup : public OptionGroup {
Jim Inghamb842f2e2017-09-14 20:22:49 +00001689public:
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001690 BreakpointAccessOptionGroup() : OptionGroup() {}
1691
Jim Inghamb842f2e2017-09-14 20:22:49 +00001692 ~BreakpointAccessOptionGroup() override = default;
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00001693
Jim Inghamb842f2e2017-09-14 20:22:49 +00001694 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1695 return llvm::makeArrayRef(g_breakpoint_access_options);
1696 }
1697 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1698 ExecutionContext *execution_context) override {
1699 Status error;
1700 const int short_option
1701 = g_breakpoint_access_options[option_idx].short_option;
1702
1703 switch (short_option) {
1704 case 'L': {
1705 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001706 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001707 if (success) {
1708 m_permissions.SetAllowList(value);
1709 } else
1710 error.SetErrorStringWithFormat(
1711 "invalid boolean value '%s' passed for -L option",
1712 option_arg.str().c_str());
1713 } break;
1714 case 'A': {
1715 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001716 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001717 if (success) {
1718 m_permissions.SetAllowDisable(value);
1719 } else
1720 error.SetErrorStringWithFormat(
1721 "invalid boolean value '%s' passed for -L option",
1722 option_arg.str().c_str());
1723 } break;
1724 case 'D': {
1725 bool value, success;
Pavel Labath47cbf4a2018-04-10 09:03:59 +00001726 value = OptionArgParser::ToBoolean(option_arg, false, &success);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001727 if (success) {
1728 m_permissions.SetAllowDelete(value);
1729 } else
1730 error.SetErrorStringWithFormat(
1731 "invalid boolean value '%s' passed for -L option",
1732 option_arg.str().c_str());
1733 } break;
1734
1735 }
1736
1737 return error;
1738 }
1739
1740 void OptionParsingStarting(ExecutionContext *execution_context) override {
1741 }
1742
1743 const BreakpointName::Permissions &GetPermissions() const
1744 {
1745 return m_permissions;
1746 }
1747 BreakpointName::Permissions m_permissions;
1748};
1749
1750class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1751public:
1752 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1753 : CommandObjectParsed(
1754 interpreter, "configure", "Configure the options for the breakpoint"
1755 " name provided. "
1756 "If you provide a breakpoint id, the options will be copied from "
1757 "the breakpoint, otherwise only the options specified will be set "
1758 "on the name.",
1759 "breakpoint name configure <command-options> "
1760 "<breakpoint-name-list>"),
1761 m_bp_opts(), m_option_group() {
1762 // Create the first variant for the first (and only) argument for this
1763 // command.
1764 CommandArgumentEntry arg1;
1765 CommandArgumentData id_arg;
1766 id_arg.arg_type = eArgTypeBreakpointName;
1767 id_arg.arg_repetition = eArgRepeatOptional;
1768 arg1.push_back(id_arg);
1769 m_arguments.push_back(arg1);
1770
1771 m_option_group.Append(&m_bp_opts,
1772 LLDB_OPT_SET_ALL,
1773 LLDB_OPT_SET_1);
1774 m_option_group.Append(&m_access_options,
1775 LLDB_OPT_SET_ALL,
1776 LLDB_OPT_SET_ALL);
Jim Inghame9632eb2017-09-15 00:52:35 +00001777 m_option_group.Append(&m_bp_id,
1778 LLDB_OPT_SET_2|LLDB_OPT_SET_4,
1779 LLDB_OPT_SET_ALL);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001780 m_option_group.Finalize();
1781 }
1782
1783 ~CommandObjectBreakpointNameConfigure() override = default;
1784
1785 Options *GetOptions() override { return &m_option_group; }
1786
1787protected:
1788 bool DoExecute(Args &command, CommandReturnObject &result) override {
1789
1790 const size_t argc = command.GetArgumentCount();
1791 if (argc == 0) {
1792 result.AppendError("No names provided.");
1793 result.SetStatus(eReturnStatusFailed);
1794 return false;
1795 }
1796
1797 Target *target =
1798 GetSelectedOrDummyTarget(false);
1799
1800 if (target == nullptr) {
1801 result.AppendError("Invalid target. No existing target or breakpoints.");
1802 result.SetStatus(eReturnStatusFailed);
1803 return false;
1804 }
1805
1806 std::unique_lock<std::recursive_mutex> lock;
1807 target->GetBreakpointList().GetListMutex(lock);
1808
1809 // Make a pass through first to see that all the names are legal.
1810 for (auto &entry : command.entries()) {
1811 Status error;
1812 if (!BreakpointID::StringIsBreakpointName(entry.ref, error))
1813 {
1814 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1815 entry.c_str(), error.AsCString());
1816 result.SetStatus(eReturnStatusFailed);
1817 return false;
1818 }
1819 }
Adrian Prantl05097242018-04-30 16:49:04 +00001820 // Now configure them, we already pre-checked the names so we don't need to
1821 // check the error:
Jim Inghamb842f2e2017-09-14 20:22:49 +00001822 BreakpointSP bp_sp;
1823 if (m_bp_id.m_breakpoint.OptionWasSet())
1824 {
1825 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value();
1826 bp_sp = target->GetBreakpointByID(bp_id);
1827 if (!bp_sp)
1828 {
1829 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1830 bp_id);
1831 result.SetStatus(eReturnStatusFailed);
1832 return false;
1833 }
1834 }
1835
1836 Status error;
1837 for (auto &entry : command.entries()) {
1838 ConstString name(entry.c_str());
1839 BreakpointName *bp_name = target->FindBreakpointName(name, true, error);
1840 if (!bp_name)
1841 continue;
Jim Inghame9632eb2017-09-15 00:52:35 +00001842 if (m_bp_id.m_help_string.OptionWasSet())
1843 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str());
1844
Jim Inghamb842f2e2017-09-14 20:22:49 +00001845 if (bp_sp)
1846 target->ConfigureBreakpointName(*bp_name,
1847 *bp_sp->GetOptions(),
1848 m_access_options.GetPermissions());
1849 else
1850 target->ConfigureBreakpointName(*bp_name,
1851 m_bp_opts.GetBreakpointOptions(),
1852 m_access_options.GetPermissions());
1853 }
1854 return true;
1855 }
1856
1857private:
1858 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1859 BreakpointOptionGroup m_bp_opts;
1860 BreakpointAccessOptionGroup m_access_options;
1861 OptionGroupOptions m_option_group;
1862};
1863
Kate Stoneb9c1b512016-09-06 20:57:50 +00001864class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001865public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001866 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1867 : CommandObjectParsed(
1868 interpreter, "add", "Add a name to the breakpoints provided.",
1869 "breakpoint name add <command-options> <breakpoint-id-list>"),
1870 m_name_options(), m_option_group() {
1871 // Create the first variant for the first (and only) argument for this
1872 // command.
1873 CommandArgumentEntry arg1;
1874 CommandArgumentData id_arg;
1875 id_arg.arg_type = eArgTypeBreakpointID;
1876 id_arg.arg_repetition = eArgRepeatOptional;
1877 arg1.push_back(id_arg);
1878 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001879
Kate Stoneb9c1b512016-09-06 20:57:50 +00001880 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1881 m_option_group.Finalize();
1882 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001883
Kate Stoneb9c1b512016-09-06 20:57:50 +00001884 ~CommandObjectBreakpointNameAdd() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001885
Kate Stoneb9c1b512016-09-06 20:57:50 +00001886 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001887
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001888protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001889 bool DoExecute(Args &command, CommandReturnObject &result) override {
1890 if (!m_name_options.m_name.OptionWasSet()) {
1891 result.SetError("No name option provided.");
1892 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001893 }
1894
Kate Stoneb9c1b512016-09-06 20:57:50 +00001895 Target *target =
1896 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1897
1898 if (target == nullptr) {
1899 result.AppendError("Invalid target. No existing target or breakpoints.");
1900 result.SetStatus(eReturnStatusFailed);
1901 return false;
1902 }
1903
1904 std::unique_lock<std::recursive_mutex> lock;
1905 target->GetBreakpointList().GetListMutex(lock);
1906
1907 const BreakpointList &breakpoints = target->GetBreakpointList();
1908
1909 size_t num_breakpoints = breakpoints.GetSize();
1910 if (num_breakpoints == 0) {
1911 result.SetError("No breakpoints, cannot add names.");
1912 result.SetStatus(eReturnStatusFailed);
1913 return false;
1914 }
1915
1916 // Particular breakpoint selected; disable that breakpoint.
1917 BreakpointIDList valid_bp_ids;
1918 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00001919 command, target, result, &valid_bp_ids,
1920 BreakpointName::Permissions::PermissionKinds::listPerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001921
1922 if (result.Succeeded()) {
1923 if (valid_bp_ids.GetSize() == 0) {
1924 result.SetError("No breakpoints specified, cannot add names.");
1925 result.SetStatus(eReturnStatusFailed);
1926 return false;
1927 }
1928 size_t num_valid_ids = valid_bp_ids.GetSize();
Jim Inghamb842f2e2017-09-14 20:22:49 +00001929 const char *bp_name = m_name_options.m_name.GetCurrentValue();
1930 Status error; // This error reports illegal names, but we've already
1931 // checked that, so we don't need to check it again here.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001932 for (size_t index = 0; index < num_valid_ids; index++) {
1933 lldb::break_id_t bp_id =
1934 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1935 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00001936 target->AddNameToBreakpoint(bp_sp, bp_name, error);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001937 }
1938 }
1939
1940 return true;
1941 }
1942
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001943private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001944 BreakpointNameOptionGroup m_name_options;
1945 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001946};
1947
Kate Stoneb9c1b512016-09-06 20:57:50 +00001948class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001949public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001950 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1951 : CommandObjectParsed(
1952 interpreter, "delete",
1953 "Delete a name from the breakpoints provided.",
1954 "breakpoint name delete <command-options> <breakpoint-id-list>"),
1955 m_name_options(), m_option_group() {
1956 // Create the first variant for the first (and only) argument for this
1957 // command.
1958 CommandArgumentEntry arg1;
1959 CommandArgumentData id_arg;
1960 id_arg.arg_type = eArgTypeBreakpointID;
1961 id_arg.arg_repetition = eArgRepeatOptional;
1962 arg1.push_back(id_arg);
1963 m_arguments.push_back(arg1);
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001964
Kate Stoneb9c1b512016-09-06 20:57:50 +00001965 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1966 m_option_group.Finalize();
1967 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001968
Kate Stoneb9c1b512016-09-06 20:57:50 +00001969 ~CommandObjectBreakpointNameDelete() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001970
Kate Stoneb9c1b512016-09-06 20:57:50 +00001971 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00001972
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001973protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001974 bool DoExecute(Args &command, CommandReturnObject &result) override {
1975 if (!m_name_options.m_name.OptionWasSet()) {
1976 result.SetError("No name option provided.");
1977 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00001978 }
1979
Kate Stoneb9c1b512016-09-06 20:57:50 +00001980 Target *target =
1981 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
1982
1983 if (target == nullptr) {
1984 result.AppendError("Invalid target. No existing target or breakpoints.");
1985 result.SetStatus(eReturnStatusFailed);
1986 return false;
1987 }
1988
1989 std::unique_lock<std::recursive_mutex> lock;
1990 target->GetBreakpointList().GetListMutex(lock);
1991
1992 const BreakpointList &breakpoints = target->GetBreakpointList();
1993
1994 size_t num_breakpoints = breakpoints.GetSize();
1995 if (num_breakpoints == 0) {
1996 result.SetError("No breakpoints, cannot delete names.");
1997 result.SetStatus(eReturnStatusFailed);
1998 return false;
1999 }
2000
2001 // Particular breakpoint selected; disable that breakpoint.
2002 BreakpointIDList valid_bp_ids;
2003 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002004 command, target, result, &valid_bp_ids,
2005 BreakpointName::Permissions::PermissionKinds::deletePerm);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002006
2007 if (result.Succeeded()) {
2008 if (valid_bp_ids.GetSize() == 0) {
2009 result.SetError("No breakpoints specified, cannot delete names.");
2010 result.SetStatus(eReturnStatusFailed);
2011 return false;
2012 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002013 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
Kate Stoneb9c1b512016-09-06 20:57:50 +00002014 size_t num_valid_ids = valid_bp_ids.GetSize();
2015 for (size_t index = 0; index < num_valid_ids; index++) {
2016 lldb::break_id_t bp_id =
2017 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
2018 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002019 target->RemoveNameFromBreakpoint(bp_sp, bp_name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002020 }
2021 }
2022
2023 return true;
2024 }
2025
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002026private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002027 BreakpointNameOptionGroup m_name_options;
2028 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002029};
2030
Kate Stoneb9c1b512016-09-06 20:57:50 +00002031class CommandObjectBreakpointNameList : public CommandObjectParsed {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002032public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002033 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
2034 : CommandObjectParsed(interpreter, "list",
Jim Inghamb842f2e2017-09-14 20:22:49 +00002035 "List either the names for a breakpoint or info "
2036 "about a given name. With no arguments, lists all "
2037 "names",
Kate Stoneb9c1b512016-09-06 20:57:50 +00002038 "breakpoint name list <command-options>"),
2039 m_name_options(), m_option_group() {
Jim Inghamb842f2e2017-09-14 20:22:49 +00002040 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002041 m_option_group.Finalize();
2042 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002043
Kate Stoneb9c1b512016-09-06 20:57:50 +00002044 ~CommandObjectBreakpointNameList() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002045
Kate Stoneb9c1b512016-09-06 20:57:50 +00002046 Options *GetOptions() override { return &m_option_group; }
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002047
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002048protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002049 bool DoExecute(Args &command, CommandReturnObject &result) override {
2050 Target *target =
2051 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue());
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002052
Kate Stoneb9c1b512016-09-06 20:57:50 +00002053 if (target == nullptr) {
2054 result.AppendError("Invalid target. No existing target or breakpoints.");
2055 result.SetStatus(eReturnStatusFailed);
2056 return false;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002057 }
Jim Inghamb842f2e2017-09-14 20:22:49 +00002058
2059
2060 std::vector<std::string> name_list;
2061 if (command.empty()) {
2062 target->GetBreakpointNames(name_list);
2063 } else {
2064 for (const Args::ArgEntry &arg : command)
2065 {
2066 name_list.push_back(arg.c_str());
2067 }
2068 }
2069
2070 if (name_list.empty()) {
2071 result.AppendMessage("No breakpoint names found.");
2072 } else {
2073 for (const std::string &name_str : name_list) {
2074 const char *name = name_str.c_str();
2075 // First print out the options for the name:
2076 Status error;
2077 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name),
2078 false,
2079 error);
2080 if (bp_name)
2081 {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002082 StreamString s;
Jim Inghamb842f2e2017-09-14 20:22:49 +00002083 result.AppendMessageWithFormat("Name: %s\n", name);
2084 if (bp_name->GetDescription(&s, eDescriptionLevelFull))
2085 {
2086 result.AppendMessage(s.GetString());
2087 }
2088
2089 std::unique_lock<std::recursive_mutex> lock;
2090 target->GetBreakpointList().GetListMutex(lock);
2091
2092 BreakpointList &breakpoints = target->GetBreakpointList();
2093 bool any_set = false;
2094 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
2095 if (bp_sp->MatchesName(name)) {
2096 StreamString s;
2097 any_set = true;
2098 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
2099 s.EOL();
2100 result.AppendMessage(s.GetString());
2101 }
2102 }
2103 if (!any_set)
2104 result.AppendMessage("No breakpoints using this name.");
2105 } else {
2106 result.AppendMessageWithFormat("Name: %s not found.\n", name);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002107 }
2108 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002109 }
2110 return true;
2111 }
2112
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002113private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002114 BreakpointNameOptionGroup m_name_options;
2115 OptionGroupOptions m_option_group;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002116};
2117
Jim Inghame14dc262016-09-12 23:10:56 +00002118// CommandObjectBreakpointName
Kate Stoneb9c1b512016-09-06 20:57:50 +00002119class CommandObjectBreakpointName : public CommandObjectMultiword {
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002120public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00002121 CommandObjectBreakpointName(CommandInterpreter &interpreter)
2122 : CommandObjectMultiword(
2123 interpreter, "name", "Commands to manage name tags for breakpoints",
2124 "breakpoint name <subcommand> [<command-options>]") {
2125 CommandObjectSP add_command_object(
2126 new CommandObjectBreakpointNameAdd(interpreter));
2127 CommandObjectSP delete_command_object(
2128 new CommandObjectBreakpointNameDelete(interpreter));
2129 CommandObjectSP list_command_object(
2130 new CommandObjectBreakpointNameList(interpreter));
Jim Inghamb842f2e2017-09-14 20:22:49 +00002131 CommandObjectSP configure_command_object(
2132 new CommandObjectBreakpointNameConfigure(interpreter));
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002133
Kate Stoneb9c1b512016-09-06 20:57:50 +00002134 LoadSubCommand("add", add_command_object);
2135 LoadSubCommand("delete", delete_command_object);
2136 LoadSubCommand("list", list_command_object);
Jim Inghamb842f2e2017-09-14 20:22:49 +00002137 LoadSubCommand("configure", configure_command_object);
Kate Stoneb9c1b512016-09-06 20:57:50 +00002138 }
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002139
Kate Stoneb9c1b512016-09-06 20:57:50 +00002140 ~CommandObjectBreakpointName() override = default;
Jim Ingham5e09c8c2014-12-16 23:40:14 +00002141};
2142
Jim Inghame14dc262016-09-12 23:10:56 +00002143// CommandObjectBreakpointRead
Jim Ingham3acdf382016-09-22 22:20:28 +00002144#pragma mark Read::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002145static constexpr OptionDefinition g_breakpoint_read_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +00002146#define LLDB_OPTIONS_breakpoint_read
2147#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002148};
2149
2150#pragma mark Read
Jim Inghame14dc262016-09-12 23:10:56 +00002151
2152class CommandObjectBreakpointRead : public CommandObjectParsed {
2153public:
2154 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2155 : CommandObjectParsed(interpreter, "breakpoint read",
2156 "Read and set the breakpoints previously saved to "
2157 "a file with \"breakpoint write\". ",
2158 nullptr),
2159 m_options() {
2160 CommandArgumentEntry arg;
2161 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2162 eArgTypeBreakpointIDRange);
2163 // Add the entry for the first argument for this command to the object's
2164 // arguments vector.
2165 m_arguments.push_back(arg);
2166 }
2167
2168 ~CommandObjectBreakpointRead() override = default;
2169
2170 Options *GetOptions() override { return &m_options; }
2171
2172 class CommandOptions : public Options {
2173 public:
2174 CommandOptions() : Options() {}
2175
2176 ~CommandOptions() override = default;
2177
Zachary Turner97206d52017-05-12 04:51:55 +00002178 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2179 ExecutionContext *execution_context) override {
2180 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002181 const int short_option = m_getopt_table[option_idx].val;
2182
2183 switch (short_option) {
2184 case 'f':
2185 m_filename.assign(option_arg);
2186 break;
Jim Ingham3acdf382016-09-22 22:20:28 +00002187 case 'N': {
Zachary Turner97206d52017-05-12 04:51:55 +00002188 Status name_error;
Jim Ingham3acdf382016-09-22 22:20:28 +00002189 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2190 name_error)) {
2191 error.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2192 name_error.AsCString());
2193 }
2194 m_names.push_back(option_arg);
2195 break;
2196 }
Jim Inghame14dc262016-09-12 23:10:56 +00002197 default:
2198 error.SetErrorStringWithFormat("unrecognized option '%c'",
2199 short_option);
2200 break;
2201 }
2202
2203 return error;
2204 }
2205
2206 void OptionParsingStarting(ExecutionContext *execution_context) override {
2207 m_filename.clear();
Jim Ingham3acdf382016-09-22 22:20:28 +00002208 m_names.clear();
Jim Inghame14dc262016-09-12 23:10:56 +00002209 }
2210
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002211 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002212 return llvm::makeArrayRef(g_breakpoint_read_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002213 }
Jim Inghame14dc262016-09-12 23:10:56 +00002214
2215 // Instance variables to hold the values for command options.
2216
2217 std::string m_filename;
Jim Ingham3acdf382016-09-22 22:20:28 +00002218 std::vector<std::string> m_names;
Jim Inghame14dc262016-09-12 23:10:56 +00002219 };
2220
2221protected:
2222 bool DoExecute(Args &command, CommandReturnObject &result) override {
2223 Target *target = GetSelectedOrDummyTarget();
2224 if (target == nullptr) {
2225 result.AppendError("Invalid target. No existing target or breakpoints.");
2226 result.SetStatus(eReturnStatusFailed);
2227 return false;
2228 }
2229
Jim Ingham3acdf382016-09-22 22:20:28 +00002230 std::unique_lock<std::recursive_mutex> lock;
2231 target->GetBreakpointList().GetListMutex(lock);
2232
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002233 FileSpec input_spec(m_options.m_filename);
2234 FileSystem::Instance().Resolve(input_spec);
Jim Ingham01f16662016-09-14 19:07:35 +00002235 BreakpointIDList new_bps;
Zachary Turner97206d52017-05-12 04:51:55 +00002236 Status error = target->CreateBreakpointsFromFile(
2237 input_spec, m_options.m_names, new_bps);
Jim Ingham01f16662016-09-14 19:07:35 +00002238
Jim Inghame14dc262016-09-12 23:10:56 +00002239 if (!error.Success()) {
Jim Ingham01f16662016-09-14 19:07:35 +00002240 result.AppendError(error.AsCString());
Jim Inghame14dc262016-09-12 23:10:56 +00002241 result.SetStatus(eReturnStatusFailed);
2242 return false;
2243 }
Jim Ingham3acdf382016-09-22 22:20:28 +00002244
2245 Stream &output_stream = result.GetOutputStream();
2246
2247 size_t num_breakpoints = new_bps.GetSize();
2248 if (num_breakpoints == 0) {
2249 result.AppendMessage("No breakpoints added.");
2250 } else {
2251 // No breakpoint selected; show info about all currently set breakpoints.
2252 result.AppendMessage("New breakpoints:");
2253 for (size_t i = 0; i < num_breakpoints; ++i) {
2254 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2255 Breakpoint *bp = target->GetBreakpointList()
2256 .FindBreakpointByID(bp_id.GetBreakpointID())
2257 .get();
2258 if (bp)
2259 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2260 false);
2261 }
2262 }
Jim Inghame14dc262016-09-12 23:10:56 +00002263 return result.Succeeded();
2264 }
2265
2266private:
2267 CommandOptions m_options;
2268};
2269
Jim Inghame14dc262016-09-12 23:10:56 +00002270// CommandObjectBreakpointWrite
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002271#pragma mark Write::CommandOptions
Tatyana Krasnukha8fe53c492018-09-26 18:50:19 +00002272static constexpr OptionDefinition g_breakpoint_write_options[] = {
Raphael Isemannf94668e2019-07-22 10:02:09 +00002273#define LLDB_OPTIONS_breakpoint_write
2274#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002275};
2276
2277#pragma mark Write
Jim Inghame14dc262016-09-12 23:10:56 +00002278class CommandObjectBreakpointWrite : public CommandObjectParsed {
2279public:
2280 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2281 : CommandObjectParsed(interpreter, "breakpoint write",
2282 "Write the breakpoints listed to a file that can "
2283 "be read in with \"breakpoint read\". "
2284 "If given no arguments, writes all breakpoints.",
2285 nullptr),
2286 m_options() {
2287 CommandArgumentEntry arg;
2288 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID,
2289 eArgTypeBreakpointIDRange);
2290 // Add the entry for the first argument for this command to the object's
2291 // arguments vector.
2292 m_arguments.push_back(arg);
2293 }
2294
2295 ~CommandObjectBreakpointWrite() override = default;
2296
2297 Options *GetOptions() override { return &m_options; }
2298
2299 class CommandOptions : public Options {
2300 public:
2301 CommandOptions() : Options() {}
2302
2303 ~CommandOptions() override = default;
2304
Zachary Turner97206d52017-05-12 04:51:55 +00002305 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2306 ExecutionContext *execution_context) override {
2307 Status error;
Jim Inghame14dc262016-09-12 23:10:56 +00002308 const int short_option = m_getopt_table[option_idx].val;
2309
2310 switch (short_option) {
2311 case 'f':
2312 m_filename.assign(option_arg);
2313 break;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002314 case 'a':
2315 m_append = true;
2316 break;
Jim Inghame14dc262016-09-12 23:10:56 +00002317 default:
2318 error.SetErrorStringWithFormat("unrecognized option '%c'",
2319 short_option);
2320 break;
2321 }
2322
2323 return error;
2324 }
2325
2326 void OptionParsingStarting(ExecutionContext *execution_context) override {
2327 m_filename.clear();
Jim Ingham2d3628e2016-09-22 23:42:42 +00002328 m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002329 }
2330
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002331 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00002332 return llvm::makeArrayRef(g_breakpoint_write_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00002333 }
Jim Inghame14dc262016-09-12 23:10:56 +00002334
2335 // Instance variables to hold the values for command options.
2336
2337 std::string m_filename;
Jim Ingham2d3628e2016-09-22 23:42:42 +00002338 bool m_append = false;
Jim Inghame14dc262016-09-12 23:10:56 +00002339 };
2340
2341protected:
2342 bool DoExecute(Args &command, CommandReturnObject &result) override {
2343 Target *target = GetSelectedOrDummyTarget();
2344 if (target == nullptr) {
2345 result.AppendError("Invalid target. No existing target or breakpoints.");
2346 result.SetStatus(eReturnStatusFailed);
2347 return false;
2348 }
2349
Jim Inghame14dc262016-09-12 23:10:56 +00002350 std::unique_lock<std::recursive_mutex> lock;
2351 target->GetBreakpointList().GetListMutex(lock);
2352
Jim Ingham01f16662016-09-14 19:07:35 +00002353 BreakpointIDList valid_bp_ids;
Zachary Turner11eb9c62016-10-05 20:03:37 +00002354 if (!command.empty()) {
Jim Inghame14dc262016-09-12 23:10:56 +00002355 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
Jim Inghamb842f2e2017-09-14 20:22:49 +00002356 command, target, result, &valid_bp_ids,
2357 BreakpointName::Permissions::PermissionKinds::listPerm);
Jim Inghame14dc262016-09-12 23:10:56 +00002358
Jim Ingham01f16662016-09-14 19:07:35 +00002359 if (!result.Succeeded()) {
2360 result.SetStatus(eReturnStatusFailed);
2361 return false;
Jim Inghame14dc262016-09-12 23:10:56 +00002362 }
2363 }
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00002364 FileSpec file_spec(m_options.m_filename);
2365 FileSystem::Instance().Resolve(file_spec);
2366 Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2367 m_options.m_append);
Jim Ingham01f16662016-09-14 19:07:35 +00002368 if (!error.Success()) {
2369 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2370 error.AsCString());
2371 result.SetStatus(eReturnStatusFailed);
2372 }
Jim Inghame14dc262016-09-12 23:10:56 +00002373 return result.Succeeded();
2374 }
2375
2376private:
2377 CommandOptions m_options;
2378};
2379
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002380// CommandObjectMultiwordBreakpoint
Jim Inghamae1c4cf2010-06-18 00:58:52 +00002381#pragma mark MultiwordBreakpoint
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002382
Kate Stoneb9c1b512016-09-06 20:57:50 +00002383CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2384 CommandInterpreter &interpreter)
2385 : CommandObjectMultiword(
2386 interpreter, "breakpoint",
2387 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2388 "breakpoint <subcommand> [<command-options>]") {
2389 CommandObjectSP list_command_object(
2390 new CommandObjectBreakpointList(interpreter));
2391 CommandObjectSP enable_command_object(
2392 new CommandObjectBreakpointEnable(interpreter));
2393 CommandObjectSP disable_command_object(
2394 new CommandObjectBreakpointDisable(interpreter));
2395 CommandObjectSP clear_command_object(
2396 new CommandObjectBreakpointClear(interpreter));
2397 CommandObjectSP delete_command_object(
2398 new CommandObjectBreakpointDelete(interpreter));
2399 CommandObjectSP set_command_object(
2400 new CommandObjectBreakpointSet(interpreter));
2401 CommandObjectSP command_command_object(
2402 new CommandObjectBreakpointCommand(interpreter));
2403 CommandObjectSP modify_command_object(
2404 new CommandObjectBreakpointModify(interpreter));
2405 CommandObjectSP name_command_object(
2406 new CommandObjectBreakpointName(interpreter));
Jim Inghame14dc262016-09-12 23:10:56 +00002407 CommandObjectSP write_command_object(
2408 new CommandObjectBreakpointWrite(interpreter));
2409 CommandObjectSP read_command_object(
2410 new CommandObjectBreakpointRead(interpreter));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002411
Kate Stoneb9c1b512016-09-06 20:57:50 +00002412 list_command_object->SetCommandName("breakpoint list");
2413 enable_command_object->SetCommandName("breakpoint enable");
2414 disable_command_object->SetCommandName("breakpoint disable");
2415 clear_command_object->SetCommandName("breakpoint clear");
2416 delete_command_object->SetCommandName("breakpoint delete");
2417 set_command_object->SetCommandName("breakpoint set");
2418 command_command_object->SetCommandName("breakpoint command");
2419 modify_command_object->SetCommandName("breakpoint modify");
2420 name_command_object->SetCommandName("breakpoint name");
Jim Inghame14dc262016-09-12 23:10:56 +00002421 write_command_object->SetCommandName("breakpoint write");
2422 read_command_object->SetCommandName("breakpoint read");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002423
Kate Stoneb9c1b512016-09-06 20:57:50 +00002424 LoadSubCommand("list", list_command_object);
2425 LoadSubCommand("enable", enable_command_object);
2426 LoadSubCommand("disable", disable_command_object);
2427 LoadSubCommand("clear", clear_command_object);
2428 LoadSubCommand("delete", delete_command_object);
2429 LoadSubCommand("set", set_command_object);
2430 LoadSubCommand("command", command_command_object);
2431 LoadSubCommand("modify", modify_command_object);
2432 LoadSubCommand("name", name_command_object);
Jim Inghame14dc262016-09-12 23:10:56 +00002433 LoadSubCommand("write", write_command_object);
2434 LoadSubCommand("read", read_command_object);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002435}
2436
Eugene Zelenko9e85e5a2016-02-18 22:39:14 +00002437CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002438
Kate Stoneb9c1b512016-09-06 20:57:50 +00002439void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target,
2440 bool allow_locations,
2441 CommandReturnObject &result,
Jim Inghamb842f2e2017-09-14 20:22:49 +00002442 BreakpointIDList *valid_ids,
2443 BreakpointName::Permissions
2444 ::PermissionKinds
2445 purpose) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002446 // args can be strings representing 1). integers (for breakpoint ids)
2447 // 2). the full breakpoint & location
2448 // canonical representation
2449 // 3). the word "to" or a hyphen,
2450 // representing a range (in which case there
2451 // had *better* be an entry both before &
2452 // after of one of the first two types.
2453 // 4). A breakpoint name
2454 // If args is empty, we will use the last created breakpoint (if there is
2455 // one.)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002456
Kate Stoneb9c1b512016-09-06 20:57:50 +00002457 Args temp_args;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002458
Zachary Turner11eb9c62016-10-05 20:03:37 +00002459 if (args.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00002460 if (target->GetLastCreatedBreakpoint()) {
2461 valid_ids->AddBreakpointID(BreakpointID(
2462 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2463 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2464 } else {
2465 result.AppendError(
2466 "No breakpoint specified and no last created breakpoint.");
2467 result.SetStatus(eReturnStatusFailed);
Jim Ingham36f3b362010-10-14 23:45:03 +00002468 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002469 return;
2470 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002471
Kate Stoneb9c1b512016-09-06 20:57:50 +00002472 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
Adrian Prantl05097242018-04-30 16:49:04 +00002473 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2474 // id range strings over; instead generate a list of strings for all the
2475 // breakpoint ids in the range, and shove all of those breakpoint id strings
2476 // into TEMP_ARGS.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002477
Jim Inghamb842f2e2017-09-14 20:22:49 +00002478 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations,
2479 purpose, result, temp_args);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002480
Kate Stoneb9c1b512016-09-06 20:57:50 +00002481 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2482 // BreakpointIDList:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002483
Pavel Labath16662f32018-06-20 08:12:50 +00002484 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002485
Adrian Prantl05097242018-04-30 16:49:04 +00002486 // At this point, all of the breakpoint ids that the user passed in have
2487 // been converted to breakpoint IDs and put into valid_ids.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002488
Kate Stoneb9c1b512016-09-06 20:57:50 +00002489 if (result.Succeeded()) {
2490 // Now that we've converted everything from args into a list of breakpoint
Adrian Prantl05097242018-04-30 16:49:04 +00002491 // ids, go through our tentative list of breakpoint id's and verify that
2492 // they correspond to valid/currently set breakpoints.
Kate Stoneb9c1b512016-09-06 20:57:50 +00002493
2494 const size_t count = valid_ids->GetSize();
2495 for (size_t i = 0; i < count; ++i) {
2496 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2497 Breakpoint *breakpoint =
2498 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2499 if (breakpoint != nullptr) {
2500 const size_t num_locations = breakpoint->GetNumLocations();
2501 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2502 StreamString id_str;
2503 BreakpointID::GetCanonicalReference(
2504 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2505 i = valid_ids->GetSize() + 1;
2506 result.AppendErrorWithFormat(
2507 "'%s' is not a currently valid breakpoint/location id.\n",
2508 id_str.GetData());
2509 result.SetStatus(eReturnStatusFailed);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002510 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002511 } else {
2512 i = valid_ids->GetSize() + 1;
2513 result.AppendErrorWithFormat(
2514 "'%d' is not a currently valid breakpoint ID.\n",
2515 cur_bp_id.GetBreakpointID());
2516 result.SetStatus(eReturnStatusFailed);
2517 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002518 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00002519 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00002520}