[mlir][int-range] Limit xor int range inference to i1 (#116968)
[llvm-project.git] / lldb / source / Commands / CommandObjectBreakpoint.cpp
blob494d6c50e94ac3847b6f98244006f1aba2663186
1 //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectBreakpoint.h"
10 #include "CommandObjectBreakpointCommand.h"
11 #include "lldb/Breakpoint/Breakpoint.h"
12 #include "lldb/Breakpoint/BreakpointIDList.h"
13 #include "lldb/Breakpoint/BreakpointLocation.h"
14 #include "lldb/Host/OptionParser.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionArgParser.h"
19 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
20 #include "lldb/Interpreter/OptionValueBoolean.h"
21 #include "lldb/Interpreter/OptionValueFileColonLine.h"
22 #include "lldb/Interpreter/OptionValueString.h"
23 #include "lldb/Interpreter/OptionValueUInt64.h"
24 #include "lldb/Interpreter/Options.h"
25 #include "lldb/Target/Language.h"
26 #include "lldb/Target/StackFrame.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Target/ThreadSpec.h"
29 #include "lldb/Utility/RegularExpression.h"
30 #include "lldb/Utility/StreamString.h"
32 #include <memory>
33 #include <optional>
34 #include <vector>
36 using namespace lldb;
37 using namespace lldb_private;
39 static void AddBreakpointDescription(Stream *s, Breakpoint *bp,
40 lldb::DescriptionLevel level) {
41 s->IndentMore();
42 bp->GetDescription(s, level, true);
43 s->IndentLess();
44 s->EOL();
47 // Modifiable Breakpoint Options
48 #pragma mark Modify::CommandOptions
49 #define LLDB_OPTIONS_breakpoint_modify
50 #include "CommandOptions.inc"
52 class lldb_private::BreakpointOptionGroup : public OptionGroup {
53 public:
54 BreakpointOptionGroup() : m_bp_opts(false) {}
56 ~BreakpointOptionGroup() override = default;
58 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
59 return llvm::ArrayRef(g_breakpoint_modify_options);
62 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
63 ExecutionContext *execution_context) override {
64 Status error;
65 const int short_option =
66 g_breakpoint_modify_options[option_idx].short_option;
67 const char *long_option =
68 g_breakpoint_modify_options[option_idx].long_option;
70 switch (short_option) {
71 case 'c':
72 // Normally an empty breakpoint condition marks is as unset. But we need
73 // to say it was passed in.
74 m_bp_opts.SetCondition(option_arg.str().c_str());
75 m_bp_opts.m_set_flags.Set(BreakpointOptions::eCondition);
76 break;
77 case 'C':
78 m_commands.push_back(std::string(option_arg));
79 break;
80 case 'd':
81 m_bp_opts.SetEnabled(false);
82 break;
83 case 'e':
84 m_bp_opts.SetEnabled(true);
85 break;
86 case 'G': {
87 bool value, success;
88 value = OptionArgParser::ToBoolean(option_arg, false, &success);
89 if (success)
90 m_bp_opts.SetAutoContinue(value);
91 else
92 error = Status::FromError(
93 CreateOptionParsingError(option_arg, short_option, long_option,
94 g_bool_parsing_error_message));
95 } break;
96 case 'i': {
97 uint32_t ignore_count;
98 if (option_arg.getAsInteger(0, ignore_count))
99 error = Status::FromError(
100 CreateOptionParsingError(option_arg, short_option, long_option,
101 g_int_parsing_error_message));
102 else
103 m_bp_opts.SetIgnoreCount(ignore_count);
104 } break;
105 case 'o': {
106 bool value, success;
107 value = OptionArgParser::ToBoolean(option_arg, false, &success);
108 if (success) {
109 m_bp_opts.SetOneShot(value);
110 } else
111 error = Status::FromError(
112 CreateOptionParsingError(option_arg, short_option, long_option,
113 g_bool_parsing_error_message));
114 } break;
115 case 't': {
116 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID;
117 if (option_arg == "current") {
118 if (!execution_context) {
119 error = Status::FromError(CreateOptionParsingError(
120 option_arg, short_option, long_option,
121 "No context to determine current thread"));
122 } else {
123 ThreadSP ctx_thread_sp = execution_context->GetThreadSP();
124 if (!ctx_thread_sp || !ctx_thread_sp->IsValid()) {
125 error = Status::FromError(
126 CreateOptionParsingError(option_arg, short_option, long_option,
127 "No currently selected thread"));
128 } else {
129 thread_id = ctx_thread_sp->GetID();
132 } else if (option_arg.getAsInteger(0, thread_id)) {
133 error = Status::FromError(
134 CreateOptionParsingError(option_arg, short_option, long_option,
135 g_int_parsing_error_message));
137 if (thread_id != LLDB_INVALID_THREAD_ID)
138 m_bp_opts.SetThreadID(thread_id);
139 } break;
140 case 'T':
141 m_bp_opts.GetThreadSpec()->SetName(option_arg.str().c_str());
142 break;
143 case 'q':
144 m_bp_opts.GetThreadSpec()->SetQueueName(option_arg.str().c_str());
145 break;
146 case 'x': {
147 uint32_t thread_index = UINT32_MAX;
148 if (option_arg.getAsInteger(0, thread_index)) {
149 error = Status::FromError(
150 CreateOptionParsingError(option_arg, short_option, long_option,
151 g_int_parsing_error_message));
152 } else {
153 m_bp_opts.GetThreadSpec()->SetIndex(thread_index);
155 } break;
156 default:
157 llvm_unreachable("Unimplemented option");
160 return error;
163 void OptionParsingStarting(ExecutionContext *execution_context) override {
164 m_bp_opts.Clear();
165 m_commands.clear();
168 Status OptionParsingFinished(ExecutionContext *execution_context) override {
169 if (!m_commands.empty()) {
170 auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
172 for (std::string &str : m_commands)
173 cmd_data->user_source.AppendString(str);
175 cmd_data->stop_on_error = true;
176 m_bp_opts.SetCommandDataCallback(cmd_data);
178 return Status();
181 const BreakpointOptions &GetBreakpointOptions() { return m_bp_opts; }
183 std::vector<std::string> m_commands;
184 BreakpointOptions m_bp_opts;
187 #define LLDB_OPTIONS_breakpoint_dummy
188 #include "CommandOptions.inc"
190 class BreakpointDummyOptionGroup : public OptionGroup {
191 public:
192 BreakpointDummyOptionGroup() = default;
194 ~BreakpointDummyOptionGroup() override = default;
196 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
197 return llvm::ArrayRef(g_breakpoint_dummy_options);
200 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
201 ExecutionContext *execution_context) override {
202 Status error;
203 const int short_option =
204 g_breakpoint_dummy_options[option_idx].short_option;
206 switch (short_option) {
207 case 'D':
208 m_use_dummy = true;
209 break;
210 default:
211 llvm_unreachable("Unimplemented option");
214 return error;
217 void OptionParsingStarting(ExecutionContext *execution_context) override {
218 m_use_dummy = false;
221 bool m_use_dummy;
224 #define LLDB_OPTIONS_breakpoint_set
225 #include "CommandOptions.inc"
227 // CommandObjectBreakpointSet
229 class CommandObjectBreakpointSet : public CommandObjectParsed {
230 public:
231 enum BreakpointSetType {
232 eSetTypeInvalid,
233 eSetTypeFileAndLine,
234 eSetTypeAddress,
235 eSetTypeFunctionName,
236 eSetTypeFunctionRegexp,
237 eSetTypeSourceRegexp,
238 eSetTypeException,
239 eSetTypeScripted,
242 CommandObjectBreakpointSet(CommandInterpreter &interpreter)
243 : CommandObjectParsed(
244 interpreter, "breakpoint set",
245 "Sets a breakpoint or set of breakpoints in the executable.",
246 "breakpoint set <cmd-options>"),
247 m_python_class_options("scripted breakpoint", true, 'P') {
248 // We're picking up all the normal options, commands and disable.
249 m_all_options.Append(&m_python_class_options,
250 LLDB_OPT_SET_1 | LLDB_OPT_SET_2, LLDB_OPT_SET_11);
251 m_all_options.Append(&m_bp_opts,
252 LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4,
253 LLDB_OPT_SET_ALL);
254 m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
255 m_all_options.Append(&m_options);
256 m_all_options.Finalize();
259 ~CommandObjectBreakpointSet() override = default;
261 Options *GetOptions() override { return &m_all_options; }
263 class CommandOptions : public OptionGroup {
264 public:
265 CommandOptions() = default;
267 ~CommandOptions() override = default;
269 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
270 ExecutionContext *execution_context) override {
271 Status error;
272 const int short_option =
273 g_breakpoint_set_options[option_idx].short_option;
274 const char *long_option =
275 g_breakpoint_set_options[option_idx].long_option;
277 switch (short_option) {
278 case 'a': {
279 m_load_addr = OptionArgParser::ToAddress(execution_context, option_arg,
280 LLDB_INVALID_ADDRESS, &error);
281 } break;
283 case 'A':
284 m_all_files = true;
285 break;
287 case 'b':
288 m_func_names.push_back(std::string(option_arg));
289 m_func_name_type_mask |= eFunctionNameTypeBase;
290 break;
292 case 'u':
293 if (option_arg.getAsInteger(0, m_column))
294 error = Status::FromError(
295 CreateOptionParsingError(option_arg, short_option, long_option,
296 g_int_parsing_error_message));
297 break;
299 case 'E': {
300 LanguageType language = Language::GetLanguageTypeFromString(option_arg);
302 llvm::StringRef error_context;
303 switch (language) {
304 case eLanguageTypeC89:
305 case eLanguageTypeC:
306 case eLanguageTypeC99:
307 case eLanguageTypeC11:
308 m_exception_language = eLanguageTypeC;
309 break;
310 case eLanguageTypeC_plus_plus:
311 case eLanguageTypeC_plus_plus_03:
312 case eLanguageTypeC_plus_plus_11:
313 case eLanguageTypeC_plus_plus_14:
314 m_exception_language = eLanguageTypeC_plus_plus;
315 break;
316 case eLanguageTypeObjC_plus_plus:
317 error_context =
318 "Set exception breakpoints separately for c++ and objective-c";
319 break;
320 case eLanguageTypeUnknown:
321 error_context = "Unknown language type for exception breakpoint";
322 break;
323 default:
324 if (Language *languagePlugin = Language::FindPlugin(language)) {
325 if (languagePlugin->SupportsExceptionBreakpointsOnThrow() ||
326 languagePlugin->SupportsExceptionBreakpointsOnCatch()) {
327 m_exception_language = language;
328 break;
331 error_context = "Unsupported language type for exception breakpoint";
333 if (!error_context.empty())
334 error = Status::FromError(CreateOptionParsingError(
335 option_arg, short_option, long_option, error_context));
336 } break;
338 case 'f':
339 m_filenames.AppendIfUnique(FileSpec(option_arg));
340 break;
342 case 'F':
343 m_func_names.push_back(std::string(option_arg));
344 m_func_name_type_mask |= eFunctionNameTypeFull;
345 break;
347 case 'h': {
348 bool success;
349 m_catch_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
350 if (!success)
351 error = Status::FromError(
352 CreateOptionParsingError(option_arg, short_option, long_option,
353 g_bool_parsing_error_message));
354 } break;
356 case 'H':
357 m_hardware = true;
358 break;
360 case 'K': {
361 bool success;
362 bool value;
363 value = OptionArgParser::ToBoolean(option_arg, true, &success);
364 if (value)
365 m_skip_prologue = eLazyBoolYes;
366 else
367 m_skip_prologue = eLazyBoolNo;
369 if (!success)
370 error = Status::FromError(
371 CreateOptionParsingError(option_arg, short_option, long_option,
372 g_bool_parsing_error_message));
373 } break;
375 case 'l':
376 if (option_arg.getAsInteger(0, m_line_num))
377 error = Status::FromError(
378 CreateOptionParsingError(option_arg, short_option, long_option,
379 g_int_parsing_error_message));
380 break;
382 case 'L':
383 m_language = Language::GetLanguageTypeFromString(option_arg);
384 if (m_language == eLanguageTypeUnknown)
385 error = Status::FromError(
386 CreateOptionParsingError(option_arg, short_option, long_option,
387 g_language_parsing_error_message));
388 break;
390 case 'm': {
391 bool success;
392 bool value;
393 value = OptionArgParser::ToBoolean(option_arg, true, &success);
394 if (value)
395 m_move_to_nearest_code = eLazyBoolYes;
396 else
397 m_move_to_nearest_code = eLazyBoolNo;
399 if (!success)
400 error = Status::FromError(
401 CreateOptionParsingError(option_arg, short_option, long_option,
402 g_bool_parsing_error_message));
403 break;
406 case 'M':
407 m_func_names.push_back(std::string(option_arg));
408 m_func_name_type_mask |= eFunctionNameTypeMethod;
409 break;
411 case 'n':
412 m_func_names.push_back(std::string(option_arg));
413 m_func_name_type_mask |= eFunctionNameTypeAuto;
414 break;
416 case 'N': {
417 if (BreakpointID::StringIsBreakpointName(option_arg, error))
418 m_breakpoint_names.push_back(std::string(option_arg));
419 else
420 error = Status::FromError(
421 CreateOptionParsingError(option_arg, short_option, long_option,
422 "Invalid breakpoint name"));
423 break;
426 case 'R': {
427 lldb::addr_t tmp_offset_addr;
428 tmp_offset_addr = OptionArgParser::ToAddress(execution_context,
429 option_arg, 0, &error);
430 if (error.Success())
431 m_offset_addr = tmp_offset_addr;
432 } break;
434 case 'O':
435 m_exception_extra_args.AppendArgument("-O");
436 m_exception_extra_args.AppendArgument(option_arg);
437 break;
439 case 'p':
440 m_source_text_regexp.assign(std::string(option_arg));
441 break;
443 case 'r':
444 m_func_regexp.assign(std::string(option_arg));
445 break;
447 case 's':
448 m_modules.AppendIfUnique(FileSpec(option_arg));
449 break;
451 case 'S':
452 m_func_names.push_back(std::string(option_arg));
453 m_func_name_type_mask |= eFunctionNameTypeSelector;
454 break;
456 case 'w': {
457 bool success;
458 m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success);
459 if (!success)
460 error = Status::FromError(
461 CreateOptionParsingError(option_arg, short_option, long_option,
462 g_bool_parsing_error_message));
463 } break;
465 case 'X':
466 m_source_regex_func_names.insert(std::string(option_arg));
467 break;
469 case 'y':
471 OptionValueFileColonLine value;
472 Status fcl_err = value.SetValueFromString(option_arg);
473 if (!fcl_err.Success()) {
474 error = Status::FromError(CreateOptionParsingError(
475 option_arg, short_option, long_option, fcl_err.AsCString()));
476 } else {
477 m_filenames.AppendIfUnique(value.GetFileSpec());
478 m_line_num = value.GetLineNumber();
479 m_column = value.GetColumnNumber();
481 } break;
483 default:
484 llvm_unreachable("Unimplemented option");
487 return error;
490 void OptionParsingStarting(ExecutionContext *execution_context) override {
491 m_filenames.Clear();
492 m_line_num = 0;
493 m_column = 0;
494 m_func_names.clear();
495 m_func_name_type_mask = eFunctionNameTypeNone;
496 m_func_regexp.clear();
497 m_source_text_regexp.clear();
498 m_modules.Clear();
499 m_load_addr = LLDB_INVALID_ADDRESS;
500 m_offset_addr = 0;
501 m_catch_bp = false;
502 m_throw_bp = true;
503 m_hardware = false;
504 m_exception_language = eLanguageTypeUnknown;
505 m_language = lldb::eLanguageTypeUnknown;
506 m_skip_prologue = eLazyBoolCalculate;
507 m_breakpoint_names.clear();
508 m_all_files = false;
509 m_exception_extra_args.Clear();
510 m_move_to_nearest_code = eLazyBoolCalculate;
511 m_source_regex_func_names.clear();
512 m_current_key.clear();
515 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
516 return llvm::ArrayRef(g_breakpoint_set_options);
519 // Instance variables to hold the values for command options.
521 std::string m_condition;
522 FileSpecList m_filenames;
523 uint32_t m_line_num = 0;
524 uint32_t m_column = 0;
525 std::vector<std::string> m_func_names;
526 std::vector<std::string> m_breakpoint_names;
527 lldb::FunctionNameType m_func_name_type_mask = eFunctionNameTypeNone;
528 std::string m_func_regexp;
529 std::string m_source_text_regexp;
530 FileSpecList m_modules;
531 lldb::addr_t m_load_addr = 0;
532 lldb::addr_t m_offset_addr;
533 bool m_catch_bp = false;
534 bool m_throw_bp = true;
535 bool m_hardware = false; // Request to use hardware breakpoints
536 lldb::LanguageType m_exception_language = eLanguageTypeUnknown;
537 lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
538 LazyBool m_skip_prologue = eLazyBoolCalculate;
539 bool m_all_files = false;
540 Args m_exception_extra_args;
541 LazyBool m_move_to_nearest_code = eLazyBoolCalculate;
542 std::unordered_set<std::string> m_source_regex_func_names;
543 std::string m_current_key;
546 protected:
547 void DoExecute(Args &command, CommandReturnObject &result) override {
548 Target &target =
549 m_dummy_options.m_use_dummy ? GetDummyTarget() : GetTarget();
551 // The following are the various types of breakpoints that could be set:
552 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
553 // 2). -a [-s -g] (setting breakpoint by address)
554 // 3). -n [-s -g] (setting breakpoint by function name)
555 // 4). -r [-s -g] (setting breakpoint by function name regular
556 // expression)
557 // 5). -p -f (setting a breakpoint by comparing a reg-exp
558 // to source text)
559 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
560 // given language.)
562 BreakpointSetType break_type = eSetTypeInvalid;
564 if (!m_python_class_options.GetName().empty())
565 break_type = eSetTypeScripted;
566 else if (m_options.m_line_num != 0)
567 break_type = eSetTypeFileAndLine;
568 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
569 break_type = eSetTypeAddress;
570 else if (!m_options.m_func_names.empty())
571 break_type = eSetTypeFunctionName;
572 else if (!m_options.m_func_regexp.empty())
573 break_type = eSetTypeFunctionRegexp;
574 else if (!m_options.m_source_text_regexp.empty())
575 break_type = eSetTypeSourceRegexp;
576 else if (m_options.m_exception_language != eLanguageTypeUnknown)
577 break_type = eSetTypeException;
579 BreakpointSP bp_sp = nullptr;
580 FileSpec module_spec;
581 const bool internal = false;
583 // If the user didn't specify skip-prologue, having an offset should turn
584 // that off.
585 if (m_options.m_offset_addr != 0 &&
586 m_options.m_skip_prologue == eLazyBoolCalculate)
587 m_options.m_skip_prologue = eLazyBoolNo;
589 switch (break_type) {
590 case eSetTypeFileAndLine: // Breakpoint by source position
592 FileSpec file;
593 const size_t num_files = m_options.m_filenames.GetSize();
594 if (num_files == 0) {
595 if (!GetDefaultFile(target, file, result)) {
596 result.AppendError("No file supplied and no default file available.");
597 return;
599 } else if (num_files > 1) {
600 result.AppendError("Only one file at a time is allowed for file and "
601 "line breakpoints.");
602 return;
603 } else
604 file = m_options.m_filenames.GetFileSpecAtIndex(0);
606 // Only check for inline functions if
607 LazyBool check_inlines = eLazyBoolCalculate;
609 bp_sp = target.CreateBreakpoint(
610 &(m_options.m_modules), file, m_options.m_line_num,
611 m_options.m_column, m_options.m_offset_addr, check_inlines,
612 m_options.m_skip_prologue, internal, m_options.m_hardware,
613 m_options.m_move_to_nearest_code);
614 } break;
616 case eSetTypeAddress: // Breakpoint by address
618 // If a shared library has been specified, make an lldb_private::Address
619 // with the library, and use that. That way the address breakpoint
620 // will track the load location of the library.
621 size_t num_modules_specified = m_options.m_modules.GetSize();
622 if (num_modules_specified == 1) {
623 const FileSpec &file_spec =
624 m_options.m_modules.GetFileSpecAtIndex(0);
625 bp_sp = target.CreateAddressInModuleBreakpoint(
626 m_options.m_load_addr, internal, file_spec, m_options.m_hardware);
627 } else if (num_modules_specified == 0) {
628 bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal,
629 m_options.m_hardware);
630 } else {
631 result.AppendError("Only one shared library can be specified for "
632 "address breakpoints.");
633 return;
635 break;
637 case eSetTypeFunctionName: // Breakpoint by function name
639 FunctionNameType name_type_mask = m_options.m_func_name_type_mask;
641 if (name_type_mask == 0)
642 name_type_mask = eFunctionNameTypeAuto;
644 bp_sp = target.CreateBreakpoint(
645 &(m_options.m_modules), &(m_options.m_filenames),
646 m_options.m_func_names, name_type_mask, m_options.m_language,
647 m_options.m_offset_addr, m_options.m_skip_prologue, internal,
648 m_options.m_hardware);
649 } break;
651 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function
652 // name
654 RegularExpression regexp(m_options.m_func_regexp);
655 if (llvm::Error err = regexp.GetError()) {
656 result.AppendErrorWithFormat(
657 "Function name regular expression could not be compiled: %s",
658 llvm::toString(std::move(err)).c_str());
659 // Check if the incorrect regex looks like a globbing expression and
660 // warn the user about it.
661 if (!m_options.m_func_regexp.empty()) {
662 if (m_options.m_func_regexp[0] == '*' ||
663 m_options.m_func_regexp[0] == '?')
664 result.AppendWarning(
665 "Function name regex does not accept glob patterns.");
667 return;
670 bp_sp = target.CreateFuncRegexBreakpoint(
671 &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp),
672 m_options.m_language, m_options.m_skip_prologue, internal,
673 m_options.m_hardware);
674 } break;
675 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text.
677 const size_t num_files = m_options.m_filenames.GetSize();
679 if (num_files == 0 && !m_options.m_all_files) {
680 FileSpec file;
681 if (!GetDefaultFile(target, file, result)) {
682 result.AppendError(
683 "No files provided and could not find default file.");
684 return;
685 } else {
686 m_options.m_filenames.Append(file);
690 RegularExpression regexp(m_options.m_source_text_regexp);
691 if (llvm::Error err = regexp.GetError()) {
692 result.AppendErrorWithFormat(
693 "Source text regular expression could not be compiled: \"%s\"",
694 llvm::toString(std::move(err)).c_str());
695 return;
697 bp_sp = target.CreateSourceRegexBreakpoint(
698 &(m_options.m_modules), &(m_options.m_filenames),
699 m_options.m_source_regex_func_names, std::move(regexp), internal,
700 m_options.m_hardware, m_options.m_move_to_nearest_code);
701 } break;
702 case eSetTypeException: {
703 Status precond_error;
704 bp_sp = target.CreateExceptionBreakpoint(
705 m_options.m_exception_language, m_options.m_catch_bp,
706 m_options.m_throw_bp, internal, &m_options.m_exception_extra_args,
707 &precond_error);
708 if (precond_error.Fail()) {
709 result.AppendErrorWithFormat(
710 "Error setting extra exception arguments: %s",
711 precond_error.AsCString());
712 target.RemoveBreakpointByID(bp_sp->GetID());
713 return;
715 } break;
716 case eSetTypeScripted: {
718 Status error;
719 bp_sp = target.CreateScriptedBreakpoint(
720 m_python_class_options.GetName().c_str(), &(m_options.m_modules),
721 &(m_options.m_filenames), false, m_options.m_hardware,
722 m_python_class_options.GetStructuredData(), &error);
723 if (error.Fail()) {
724 result.AppendErrorWithFormat(
725 "Error setting extra exception arguments: %s", error.AsCString());
726 target.RemoveBreakpointByID(bp_sp->GetID());
727 return;
729 } break;
730 default:
731 break;
734 // Now set the various options that were passed in:
735 if (bp_sp) {
736 bp_sp->GetOptions().CopyOverSetOptions(m_bp_opts.GetBreakpointOptions());
738 if (!m_options.m_breakpoint_names.empty()) {
739 Status name_error;
740 for (auto name : m_options.m_breakpoint_names) {
741 target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error);
742 if (name_error.Fail()) {
743 result.AppendErrorWithFormat("Invalid breakpoint name: %s",
744 name.c_str());
745 target.RemoveBreakpointByID(bp_sp->GetID());
746 return;
752 if (bp_sp) {
753 Stream &output_stream = result.GetOutputStream();
754 const bool show_locations = false;
755 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
756 show_locations);
757 if (&target == &GetDummyTarget())
758 output_stream.Printf("Breakpoint set in dummy target, will get copied "
759 "into future targets.\n");
760 else {
761 // Don't print out this warning for exception breakpoints. They can
762 // get set before the target is set, but we won't know how to actually
763 // set the breakpoint till we run.
764 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) {
765 output_stream.Printf("WARNING: Unable to resolve breakpoint to any "
766 "actual locations.\n");
769 result.SetStatus(eReturnStatusSuccessFinishResult);
770 } else if (!bp_sp) {
771 result.AppendError("Breakpoint creation failed: No breakpoint created.");
775 private:
776 bool GetDefaultFile(Target &target, FileSpec &file,
777 CommandReturnObject &result) {
778 // First use the Source Manager's default file. Then use the current stack
779 // frame's file.
780 if (auto maybe_file_and_line =
781 target.GetSourceManager().GetDefaultFileAndLine()) {
782 file = maybe_file_and_line->support_file_sp->GetSpecOnly();
783 return true;
786 StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
787 if (cur_frame == nullptr) {
788 result.AppendError(
789 "No selected frame to use to find the default file.");
790 return false;
792 if (!cur_frame->HasDebugInformation()) {
793 result.AppendError("Cannot use the selected frame to find the default "
794 "file, it has no debug info.");
795 return false;
798 const SymbolContext &sc =
799 cur_frame->GetSymbolContext(eSymbolContextLineEntry);
800 if (sc.line_entry.GetFile()) {
801 file = sc.line_entry.GetFile();
802 } else {
803 result.AppendError("Can't find the file for the selected frame to "
804 "use as the default file.");
805 return false;
807 return true;
810 BreakpointOptionGroup m_bp_opts;
811 BreakpointDummyOptionGroup m_dummy_options;
812 OptionGroupPythonClassWithDict m_python_class_options;
813 CommandOptions m_options;
814 OptionGroupOptions m_all_options;
817 // CommandObjectBreakpointModify
818 #pragma mark Modify
820 class CommandObjectBreakpointModify : public CommandObjectParsed {
821 public:
822 CommandObjectBreakpointModify(CommandInterpreter &interpreter)
823 : CommandObjectParsed(interpreter, "breakpoint modify",
824 "Modify the options on a breakpoint or set of "
825 "breakpoints in the executable. "
826 "If no breakpoint is specified, acts on the last "
827 "created breakpoint. "
828 "With the exception of -e, -d and -i, passing an "
829 "empty argument clears the modification.",
830 nullptr) {
831 CommandObject::AddIDsArgumentData(eBreakpointArgs);
833 m_options.Append(&m_bp_opts,
834 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
835 LLDB_OPT_SET_ALL);
836 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
837 m_options.Finalize();
840 ~CommandObjectBreakpointModify() override = default;
842 void
843 HandleArgumentCompletion(CompletionRequest &request,
844 OptionElementVector &opt_element_vector) override {
845 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
846 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
849 Options *GetOptions() override { return &m_options; }
851 protected:
852 void DoExecute(Args &command, CommandReturnObject &result) override {
853 Target &target = m_dummy_opts.m_use_dummy ? GetDummyTarget() : GetTarget();
855 std::unique_lock<std::recursive_mutex> lock;
856 target.GetBreakpointList().GetListMutex(lock);
858 BreakpointIDList valid_bp_ids;
860 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
861 command, target, result, &valid_bp_ids,
862 BreakpointName::Permissions::PermissionKinds::disablePerm);
864 if (result.Succeeded()) {
865 const size_t count = valid_bp_ids.GetSize();
866 for (size_t i = 0; i < count; ++i) {
867 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
869 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
870 Breakpoint *bp =
871 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
872 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
873 BreakpointLocation *location =
874 bp->FindLocationByID(cur_bp_id.GetLocationID()).get();
875 if (location)
876 location->GetLocationOptions().CopyOverSetOptions(
877 m_bp_opts.GetBreakpointOptions());
878 } else {
879 bp->GetOptions().CopyOverSetOptions(
880 m_bp_opts.GetBreakpointOptions());
887 private:
888 BreakpointOptionGroup m_bp_opts;
889 BreakpointDummyOptionGroup m_dummy_opts;
890 OptionGroupOptions m_options;
893 // CommandObjectBreakpointEnable
894 #pragma mark Enable
896 class CommandObjectBreakpointEnable : public CommandObjectParsed {
897 public:
898 CommandObjectBreakpointEnable(CommandInterpreter &interpreter)
899 : CommandObjectParsed(interpreter, "enable",
900 "Enable the specified disabled breakpoint(s). If "
901 "no breakpoints are specified, enable all of them.",
902 nullptr) {
903 CommandObject::AddIDsArgumentData(eBreakpointArgs);
906 ~CommandObjectBreakpointEnable() override = default;
908 void
909 HandleArgumentCompletion(CompletionRequest &request,
910 OptionElementVector &opt_element_vector) override {
911 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
912 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
915 protected:
916 void DoExecute(Args &command, CommandReturnObject &result) override {
917 Target &target = GetTarget();
919 std::unique_lock<std::recursive_mutex> lock;
920 target.GetBreakpointList().GetListMutex(lock);
922 const BreakpointList &breakpoints = target.GetBreakpointList();
924 size_t num_breakpoints = breakpoints.GetSize();
926 if (num_breakpoints == 0) {
927 result.AppendError("No breakpoints exist to be enabled.");
928 return;
931 if (command.empty()) {
932 // No breakpoint selected; enable all currently set breakpoints.
933 target.EnableAllowedBreakpoints();
934 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
935 " breakpoints)\n",
936 (uint64_t)num_breakpoints);
937 result.SetStatus(eReturnStatusSuccessFinishNoResult);
938 } else {
939 // Particular breakpoint selected; enable that breakpoint.
940 BreakpointIDList valid_bp_ids;
941 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
942 command, target, result, &valid_bp_ids,
943 BreakpointName::Permissions::PermissionKinds::disablePerm);
945 if (result.Succeeded()) {
946 int enable_count = 0;
947 int loc_count = 0;
948 const size_t count = valid_bp_ids.GetSize();
949 for (size_t i = 0; i < count; ++i) {
950 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
952 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
953 Breakpoint *breakpoint =
954 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
955 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
956 BreakpointLocation *location =
957 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
958 if (location) {
959 location->SetEnabled(true);
960 ++loc_count;
962 } else {
963 breakpoint->SetEnabled(true);
964 ++enable_count;
968 result.AppendMessageWithFormat("%d breakpoints enabled.\n",
969 enable_count + loc_count);
970 result.SetStatus(eReturnStatusSuccessFinishNoResult);
976 // CommandObjectBreakpointDisable
977 #pragma mark Disable
979 class CommandObjectBreakpointDisable : public CommandObjectParsed {
980 public:
981 CommandObjectBreakpointDisable(CommandInterpreter &interpreter)
982 : CommandObjectParsed(
983 interpreter, "breakpoint disable",
984 "Disable the specified breakpoint(s) without deleting "
985 "them. If none are specified, disable all "
986 "breakpoints.",
987 nullptr) {
988 SetHelpLong(
989 "Disable the specified breakpoint(s) without deleting them. \
990 If none are specified, disable all breakpoints."
994 "Note: disabling a breakpoint will cause none of its locations to be hit \
995 regardless of whether individual locations are enabled or disabled. After the sequence:"
998 (lldb) break disable 1
999 (lldb) break enable 1.1
1001 execution will NOT stop at location 1.1. To achieve that, type:
1003 (lldb) break disable 1.*
1004 (lldb) break enable 1.1
1007 "The first command disables all locations for breakpoint 1, \
1008 the second re-enables the first location.");
1010 CommandObject::AddIDsArgumentData(eBreakpointArgs);
1013 ~CommandObjectBreakpointDisable() override = default;
1015 void
1016 HandleArgumentCompletion(CompletionRequest &request,
1017 OptionElementVector &opt_element_vector) override {
1018 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1019 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1022 protected:
1023 void DoExecute(Args &command, CommandReturnObject &result) override {
1024 Target &target = GetTarget();
1025 std::unique_lock<std::recursive_mutex> lock;
1026 target.GetBreakpointList().GetListMutex(lock);
1028 const BreakpointList &breakpoints = target.GetBreakpointList();
1029 size_t num_breakpoints = breakpoints.GetSize();
1031 if (num_breakpoints == 0) {
1032 result.AppendError("No breakpoints exist to be disabled.");
1033 return;
1036 if (command.empty()) {
1037 // No breakpoint selected; disable all currently set breakpoints.
1038 target.DisableAllowedBreakpoints();
1039 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1040 " breakpoints)\n",
1041 (uint64_t)num_breakpoints);
1042 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1043 } else {
1044 // Particular breakpoint selected; disable that breakpoint.
1045 BreakpointIDList valid_bp_ids;
1047 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1048 command, target, result, &valid_bp_ids,
1049 BreakpointName::Permissions::PermissionKinds::disablePerm);
1051 if (result.Succeeded()) {
1052 int disable_count = 0;
1053 int loc_count = 0;
1054 const size_t count = valid_bp_ids.GetSize();
1055 for (size_t i = 0; i < count; ++i) {
1056 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1058 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1059 Breakpoint *breakpoint =
1060 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1061 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1062 BreakpointLocation *location =
1063 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1064 if (location) {
1065 location->SetEnabled(false);
1066 ++loc_count;
1068 } else {
1069 breakpoint->SetEnabled(false);
1070 ++disable_count;
1074 result.AppendMessageWithFormat("%d breakpoints disabled.\n",
1075 disable_count + loc_count);
1076 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1082 // CommandObjectBreakpointList
1084 #pragma mark List::CommandOptions
1085 #define LLDB_OPTIONS_breakpoint_list
1086 #include "CommandOptions.inc"
1088 #pragma mark List
1090 class CommandObjectBreakpointList : public CommandObjectParsed {
1091 public:
1092 CommandObjectBreakpointList(CommandInterpreter &interpreter)
1093 : CommandObjectParsed(
1094 interpreter, "breakpoint list",
1095 "List some or all breakpoints at configurable levels of detail.",
1096 nullptr) {
1097 CommandArgumentEntry arg;
1098 CommandArgumentData bp_id_arg;
1100 // Define the first (and only) variant of this arg.
1101 AddSimpleArgumentList(eArgTypeBreakpointID, eArgRepeatOptional);
1104 ~CommandObjectBreakpointList() override = default;
1106 Options *GetOptions() override { return &m_options; }
1108 class CommandOptions : public Options {
1109 public:
1110 CommandOptions() = default;
1112 ~CommandOptions() override = default;
1114 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1115 ExecutionContext *execution_context) override {
1116 Status error;
1117 const int short_option = m_getopt_table[option_idx].val;
1119 switch (short_option) {
1120 case 'b':
1121 m_level = lldb::eDescriptionLevelBrief;
1122 break;
1123 case 'D':
1124 m_use_dummy = true;
1125 break;
1126 case 'f':
1127 m_level = lldb::eDescriptionLevelFull;
1128 break;
1129 case 'v':
1130 m_level = lldb::eDescriptionLevelVerbose;
1131 break;
1132 case 'i':
1133 m_internal = true;
1134 break;
1135 default:
1136 llvm_unreachable("Unimplemented option");
1139 return error;
1142 void OptionParsingStarting(ExecutionContext *execution_context) override {
1143 m_level = lldb::eDescriptionLevelFull;
1144 m_internal = false;
1145 m_use_dummy = false;
1148 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1149 return llvm::ArrayRef(g_breakpoint_list_options);
1152 // Instance variables to hold the values for command options.
1154 lldb::DescriptionLevel m_level = lldb::eDescriptionLevelBrief;
1156 bool m_internal;
1157 bool m_use_dummy = false;
1160 protected:
1161 void DoExecute(Args &command, CommandReturnObject &result) override {
1162 Target &target = m_options.m_use_dummy ? GetDummyTarget() : GetTarget();
1164 const BreakpointList &breakpoints =
1165 target.GetBreakpointList(m_options.m_internal);
1166 std::unique_lock<std::recursive_mutex> lock;
1167 target.GetBreakpointList(m_options.m_internal).GetListMutex(lock);
1169 size_t num_breakpoints = breakpoints.GetSize();
1171 if (num_breakpoints == 0) {
1172 result.AppendMessage("No breakpoints currently set.");
1173 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1174 return;
1177 Stream &output_stream = result.GetOutputStream();
1179 if (command.empty()) {
1180 // No breakpoint selected; show info about all currently set breakpoints.
1181 result.AppendMessage("Current breakpoints:");
1182 for (size_t i = 0; i < num_breakpoints; ++i) {
1183 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get();
1184 if (breakpoint->AllowList())
1185 AddBreakpointDescription(&output_stream, breakpoint,
1186 m_options.m_level);
1188 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1189 } else {
1190 // Particular breakpoints selected; show info about that breakpoint.
1191 BreakpointIDList valid_bp_ids;
1192 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1193 command, target, result, &valid_bp_ids,
1194 BreakpointName::Permissions::PermissionKinds::listPerm);
1196 if (result.Succeeded()) {
1197 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) {
1198 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1199 Breakpoint *breakpoint =
1200 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1201 AddBreakpointDescription(&output_stream, breakpoint,
1202 m_options.m_level);
1204 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1205 } else {
1206 result.AppendError("Invalid breakpoint ID.");
1211 private:
1212 CommandOptions m_options;
1215 // CommandObjectBreakpointClear
1216 #pragma mark Clear::CommandOptions
1218 #define LLDB_OPTIONS_breakpoint_clear
1219 #include "CommandOptions.inc"
1221 #pragma mark Clear
1223 class CommandObjectBreakpointClear : public CommandObjectParsed {
1224 public:
1225 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine };
1227 CommandObjectBreakpointClear(CommandInterpreter &interpreter)
1228 : CommandObjectParsed(interpreter, "breakpoint clear",
1229 "Delete or disable breakpoints matching the "
1230 "specified source file and line.",
1231 "breakpoint clear <cmd-options>") {}
1233 ~CommandObjectBreakpointClear() override = default;
1235 Options *GetOptions() override { return &m_options; }
1237 class CommandOptions : public Options {
1238 public:
1239 CommandOptions() = default;
1241 ~CommandOptions() override = default;
1243 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1244 ExecutionContext *execution_context) override {
1245 Status error;
1246 const int short_option = m_getopt_table[option_idx].val;
1248 switch (short_option) {
1249 case 'f':
1250 m_filename.assign(std::string(option_arg));
1251 break;
1253 case 'l':
1254 option_arg.getAsInteger(0, m_line_num);
1255 break;
1257 default:
1258 llvm_unreachable("Unimplemented option");
1261 return error;
1264 void OptionParsingStarting(ExecutionContext *execution_context) override {
1265 m_filename.clear();
1266 m_line_num = 0;
1269 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1270 return llvm::ArrayRef(g_breakpoint_clear_options);
1273 // Instance variables to hold the values for command options.
1275 std::string m_filename;
1276 uint32_t m_line_num = 0;
1279 protected:
1280 void DoExecute(Args &command, CommandReturnObject &result) override {
1281 Target &target = GetTarget();
1283 // The following are the various types of breakpoints that could be
1284 // cleared:
1285 // 1). -f -l (clearing breakpoint by source location)
1287 BreakpointClearType break_type = eClearTypeInvalid;
1289 if (m_options.m_line_num != 0)
1290 break_type = eClearTypeFileAndLine;
1292 std::unique_lock<std::recursive_mutex> lock;
1293 target.GetBreakpointList().GetListMutex(lock);
1295 BreakpointList &breakpoints = target.GetBreakpointList();
1296 size_t num_breakpoints = breakpoints.GetSize();
1298 // Early return if there's no breakpoint at all.
1299 if (num_breakpoints == 0) {
1300 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1301 return;
1304 // Find matching breakpoints and delete them.
1306 // First create a copy of all the IDs.
1307 std::vector<break_id_t> BreakIDs;
1308 for (size_t i = 0; i < num_breakpoints; ++i)
1309 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID());
1311 int num_cleared = 0;
1312 StreamString ss;
1313 switch (break_type) {
1314 case eClearTypeFileAndLine: // Breakpoint by source position
1316 const ConstString filename(m_options.m_filename.c_str());
1317 BreakpointLocationCollection loc_coll;
1319 for (size_t i = 0; i < num_breakpoints; ++i) {
1320 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get();
1322 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) {
1323 // If the collection size is 0, it's a full match and we can just
1324 // remove the breakpoint.
1325 if (loc_coll.GetSize() == 0) {
1326 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief);
1327 ss.EOL();
1328 target.RemoveBreakpointByID(bp->GetID());
1329 ++num_cleared;
1333 } break;
1335 default:
1336 break;
1339 if (num_cleared > 0) {
1340 Stream &output_stream = result.GetOutputStream();
1341 output_stream.Printf("%d breakpoints cleared:\n", num_cleared);
1342 output_stream << ss.GetString();
1343 output_stream.EOL();
1344 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1345 } else {
1346 result.AppendError("Breakpoint clear: No breakpoint cleared.");
1350 private:
1351 CommandOptions m_options;
1354 // CommandObjectBreakpointDelete
1355 #define LLDB_OPTIONS_breakpoint_delete
1356 #include "CommandOptions.inc"
1358 #pragma mark Delete
1360 class CommandObjectBreakpointDelete : public CommandObjectParsed {
1361 public:
1362 CommandObjectBreakpointDelete(CommandInterpreter &interpreter)
1363 : CommandObjectParsed(interpreter, "breakpoint delete",
1364 "Delete the specified breakpoint(s). If no "
1365 "breakpoints are specified, delete them all.",
1366 nullptr) {
1367 CommandObject::AddIDsArgumentData(eBreakpointArgs);
1370 ~CommandObjectBreakpointDelete() override = default;
1372 void
1373 HandleArgumentCompletion(CompletionRequest &request,
1374 OptionElementVector &opt_element_vector) override {
1375 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1376 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1379 Options *GetOptions() override { return &m_options; }
1381 class CommandOptions : public Options {
1382 public:
1383 CommandOptions() = default;
1385 ~CommandOptions() override = default;
1387 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1388 ExecutionContext *execution_context) override {
1389 Status error;
1390 const int short_option = m_getopt_table[option_idx].val;
1392 switch (short_option) {
1393 case 'f':
1394 m_force = true;
1395 break;
1397 case 'D':
1398 m_use_dummy = true;
1399 break;
1401 case 'd':
1402 m_delete_disabled = true;
1403 break;
1405 default:
1406 llvm_unreachable("Unimplemented option");
1409 return error;
1412 void OptionParsingStarting(ExecutionContext *execution_context) override {
1413 m_use_dummy = false;
1414 m_force = false;
1415 m_delete_disabled = false;
1418 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1419 return llvm::ArrayRef(g_breakpoint_delete_options);
1422 // Instance variables to hold the values for command options.
1423 bool m_use_dummy = false;
1424 bool m_force = false;
1425 bool m_delete_disabled = false;
1428 protected:
1429 void DoExecute(Args &command, CommandReturnObject &result) override {
1430 Target &target = m_options.m_use_dummy ? GetDummyTarget() : GetTarget();
1431 result.Clear();
1433 std::unique_lock<std::recursive_mutex> lock;
1434 target.GetBreakpointList().GetListMutex(lock);
1436 BreakpointList &breakpoints = target.GetBreakpointList();
1438 size_t num_breakpoints = breakpoints.GetSize();
1440 if (num_breakpoints == 0) {
1441 result.AppendError("No breakpoints exist to be deleted.");
1442 return;
1445 // Handle the delete all breakpoints case:
1446 if (command.empty() && !m_options.m_delete_disabled) {
1447 if (!m_options.m_force &&
1448 !m_interpreter.Confirm(
1449 "About to delete all breakpoints, do you want to do that?",
1450 true)) {
1451 result.AppendMessage("Operation cancelled...");
1452 } else {
1453 target.RemoveAllowedBreakpoints();
1454 result.AppendMessageWithFormat(
1455 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n",
1456 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : "");
1458 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1459 return;
1462 // Either we have some kind of breakpoint specification(s),
1463 // or we are handling "break disable --deleted". Gather the list
1464 // of breakpoints to delete here, the we'll delete them below.
1465 BreakpointIDList valid_bp_ids;
1467 if (m_options.m_delete_disabled) {
1468 BreakpointIDList excluded_bp_ids;
1470 if (!command.empty()) {
1471 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1472 command, target, result, &excluded_bp_ids,
1473 BreakpointName::Permissions::PermissionKinds::deletePerm);
1474 if (!result.Succeeded())
1475 return;
1478 for (auto breakpoint_sp : breakpoints.Breakpoints()) {
1479 if (!breakpoint_sp->IsEnabled() && breakpoint_sp->AllowDelete()) {
1480 BreakpointID bp_id(breakpoint_sp->GetID());
1481 if (!excluded_bp_ids.Contains(bp_id))
1482 valid_bp_ids.AddBreakpointID(bp_id);
1485 if (valid_bp_ids.GetSize() == 0) {
1486 result.AppendError("No disabled breakpoints.");
1487 return;
1489 } else {
1490 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1491 command, target, result, &valid_bp_ids,
1492 BreakpointName::Permissions::PermissionKinds::deletePerm);
1493 if (!result.Succeeded())
1494 return;
1497 int delete_count = 0;
1498 int disable_count = 0;
1499 const size_t count = valid_bp_ids.GetSize();
1500 for (size_t i = 0; i < count; ++i) {
1501 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
1503 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
1504 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
1505 Breakpoint *breakpoint =
1506 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
1507 BreakpointLocation *location =
1508 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get();
1509 // It makes no sense to try to delete individual locations, so we
1510 // disable them instead.
1511 if (location) {
1512 location->SetEnabled(false);
1513 ++disable_count;
1515 } else {
1516 target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID());
1517 ++delete_count;
1521 result.AppendMessageWithFormat(
1522 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1523 delete_count, disable_count);
1524 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1527 private:
1528 CommandOptions m_options;
1531 // CommandObjectBreakpointName
1532 #define LLDB_OPTIONS_breakpoint_name
1533 #include "CommandOptions.inc"
1535 class BreakpointNameOptionGroup : public OptionGroup {
1536 public:
1537 BreakpointNameOptionGroup()
1538 : m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) {}
1540 ~BreakpointNameOptionGroup() override = default;
1542 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1543 return llvm::ArrayRef(g_breakpoint_name_options);
1546 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1547 ExecutionContext *execution_context) override {
1548 Status error;
1549 const int short_option = g_breakpoint_name_options[option_idx].short_option;
1550 const char *long_option = g_breakpoint_name_options[option_idx].long_option;
1552 switch (short_option) {
1553 case 'N':
1554 if (BreakpointID::StringIsBreakpointName(option_arg, error) &&
1555 error.Success())
1556 m_name.SetValueFromString(option_arg);
1557 break;
1558 case 'B':
1559 if (m_breakpoint.SetValueFromString(option_arg).Fail())
1560 error = Status::FromError(
1561 CreateOptionParsingError(option_arg, short_option, long_option,
1562 g_int_parsing_error_message));
1563 break;
1564 case 'D':
1565 if (m_use_dummy.SetValueFromString(option_arg).Fail())
1566 error = Status::FromError(
1567 CreateOptionParsingError(option_arg, short_option, long_option,
1568 g_bool_parsing_error_message));
1569 break;
1570 case 'H':
1571 m_help_string.SetValueFromString(option_arg);
1572 break;
1574 default:
1575 llvm_unreachable("Unimplemented option");
1577 return error;
1580 void OptionParsingStarting(ExecutionContext *execution_context) override {
1581 m_name.Clear();
1582 m_breakpoint.Clear();
1583 m_use_dummy.Clear();
1584 m_use_dummy.SetDefaultValue(false);
1585 m_help_string.Clear();
1588 OptionValueString m_name;
1589 OptionValueUInt64 m_breakpoint;
1590 OptionValueBoolean m_use_dummy;
1591 OptionValueString m_help_string;
1594 #define LLDB_OPTIONS_breakpoint_access
1595 #include "CommandOptions.inc"
1597 class BreakpointAccessOptionGroup : public OptionGroup {
1598 public:
1599 BreakpointAccessOptionGroup() = default;
1601 ~BreakpointAccessOptionGroup() override = default;
1603 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1604 return llvm::ArrayRef(g_breakpoint_access_options);
1606 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1607 ExecutionContext *execution_context) override {
1608 Status error;
1609 const int short_option =
1610 g_breakpoint_access_options[option_idx].short_option;
1611 const char *long_option =
1612 g_breakpoint_access_options[option_idx].long_option;
1614 switch (short_option) {
1615 case 'L': {
1616 bool value, success;
1617 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1618 if (success) {
1619 m_permissions.SetAllowList(value);
1620 } else
1621 error = Status::FromError(
1622 CreateOptionParsingError(option_arg, short_option, long_option,
1623 g_bool_parsing_error_message));
1624 } break;
1625 case 'A': {
1626 bool value, success;
1627 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1628 if (success) {
1629 m_permissions.SetAllowDisable(value);
1630 } else
1631 error = Status::FromError(
1632 CreateOptionParsingError(option_arg, short_option, long_option,
1633 g_bool_parsing_error_message));
1634 } break;
1635 case 'D': {
1636 bool value, success;
1637 value = OptionArgParser::ToBoolean(option_arg, false, &success);
1638 if (success) {
1639 m_permissions.SetAllowDelete(value);
1640 } else
1641 error = Status::FromError(
1642 CreateOptionParsingError(option_arg, short_option, long_option,
1643 g_bool_parsing_error_message));
1644 } break;
1645 default:
1646 llvm_unreachable("Unimplemented option");
1649 return error;
1652 void OptionParsingStarting(ExecutionContext *execution_context) override {}
1654 const BreakpointName::Permissions &GetPermissions() const {
1655 return m_permissions;
1657 BreakpointName::Permissions m_permissions;
1660 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed {
1661 public:
1662 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter)
1663 : CommandObjectParsed(
1664 interpreter, "configure",
1665 "Configure the options for the breakpoint"
1666 " name provided. "
1667 "If you provide a breakpoint id, the options will be copied from "
1668 "the breakpoint, otherwise only the options specified will be set "
1669 "on the name.",
1670 "breakpoint name configure <command-options> "
1671 "<breakpoint-name-list>") {
1672 AddSimpleArgumentList(eArgTypeBreakpointName, eArgRepeatOptional);
1674 m_option_group.Append(&m_bp_opts, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1675 m_option_group.Append(&m_access_options, LLDB_OPT_SET_ALL,
1676 LLDB_OPT_SET_ALL);
1677 m_option_group.Append(&m_bp_id, LLDB_OPT_SET_2 | LLDB_OPT_SET_4,
1678 LLDB_OPT_SET_ALL);
1679 m_option_group.Finalize();
1682 ~CommandObjectBreakpointNameConfigure() override = default;
1684 Options *GetOptions() override { return &m_option_group; }
1686 protected:
1687 void DoExecute(Args &command, CommandReturnObject &result) override {
1689 const size_t argc = command.GetArgumentCount();
1690 if (argc == 0) {
1691 result.AppendError("No names provided.");
1692 return;
1695 Target &target = GetTarget();
1697 std::unique_lock<std::recursive_mutex> lock;
1698 target.GetBreakpointList().GetListMutex(lock);
1700 // Make a pass through first to see that all the names are legal.
1701 for (auto &entry : command.entries()) {
1702 Status error;
1703 if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) {
1704 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1705 entry.c_str(), error.AsCString());
1706 return;
1709 // Now configure them, we already pre-checked the names so we don't need to
1710 // check the error:
1711 BreakpointSP bp_sp;
1712 if (m_bp_id.m_breakpoint.OptionWasSet()) {
1713 lldb::break_id_t bp_id =
1714 m_bp_id.m_breakpoint.GetValueAs<uint64_t>().value_or(0);
1715 bp_sp = target.GetBreakpointByID(bp_id);
1716 if (!bp_sp) {
1717 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1718 bp_id);
1719 return;
1723 Status error;
1724 for (auto &entry : command.entries()) {
1725 ConstString name(entry.c_str());
1726 BreakpointName *bp_name = target.FindBreakpointName(name, true, error);
1727 if (!bp_name)
1728 continue;
1729 if (m_bp_id.m_help_string.OptionWasSet())
1730 bp_name->SetHelp(m_bp_id.m_help_string.GetValueAs<llvm::StringRef>()
1731 .value_or("")
1732 .str()
1733 .c_str());
1735 if (bp_sp)
1736 target.ConfigureBreakpointName(*bp_name, bp_sp->GetOptions(),
1737 m_access_options.GetPermissions());
1738 else
1739 target.ConfigureBreakpointName(*bp_name,
1740 m_bp_opts.GetBreakpointOptions(),
1741 m_access_options.GetPermissions());
1745 private:
1746 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this.
1747 BreakpointOptionGroup m_bp_opts;
1748 BreakpointAccessOptionGroup m_access_options;
1749 OptionGroupOptions m_option_group;
1752 class CommandObjectBreakpointNameAdd : public CommandObjectParsed {
1753 public:
1754 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter)
1755 : CommandObjectParsed(
1756 interpreter, "add", "Add a name to the breakpoints provided.",
1757 "breakpoint name add <command-options> <breakpoint-id-list>") {
1758 AddSimpleArgumentList(eArgTypeBreakpointID, eArgRepeatOptional);
1760 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1761 m_option_group.Finalize();
1764 ~CommandObjectBreakpointNameAdd() override = default;
1766 void
1767 HandleArgumentCompletion(CompletionRequest &request,
1768 OptionElementVector &opt_element_vector) override {
1769 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1770 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1773 Options *GetOptions() override { return &m_option_group; }
1775 protected:
1776 void DoExecute(Args &command, CommandReturnObject &result) override {
1777 if (!m_name_options.m_name.OptionWasSet()) {
1778 result.AppendError("No name option provided.");
1779 return;
1782 Target &target =
1783 m_name_options.m_use_dummy ? GetDummyTarget() : GetTarget();
1785 std::unique_lock<std::recursive_mutex> lock;
1786 target.GetBreakpointList().GetListMutex(lock);
1788 const BreakpointList &breakpoints = target.GetBreakpointList();
1790 size_t num_breakpoints = breakpoints.GetSize();
1791 if (num_breakpoints == 0) {
1792 result.AppendError("No breakpoints, cannot add names.");
1793 return;
1796 // Particular breakpoint selected; disable that breakpoint.
1797 BreakpointIDList valid_bp_ids;
1798 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1799 command, target, result, &valid_bp_ids,
1800 BreakpointName::Permissions::PermissionKinds::listPerm);
1802 if (result.Succeeded()) {
1803 if (valid_bp_ids.GetSize() == 0) {
1804 result.AppendError("No breakpoints specified, cannot add names.");
1805 return;
1807 size_t num_valid_ids = valid_bp_ids.GetSize();
1808 const char *bp_name = m_name_options.m_name.GetCurrentValue();
1809 Status error; // This error reports illegal names, but we've already
1810 // checked that, so we don't need to check it again here.
1811 for (size_t index = 0; index < num_valid_ids; index++) {
1812 lldb::break_id_t bp_id =
1813 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1814 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1815 target.AddNameToBreakpoint(bp_sp, bp_name, error);
1820 private:
1821 BreakpointNameOptionGroup m_name_options;
1822 OptionGroupOptions m_option_group;
1825 class CommandObjectBreakpointNameDelete : public CommandObjectParsed {
1826 public:
1827 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter)
1828 : CommandObjectParsed(
1829 interpreter, "delete",
1830 "Delete a name from the breakpoints provided.",
1831 "breakpoint name delete <command-options> <breakpoint-id-list>") {
1832 AddSimpleArgumentList(eArgTypeBreakpointID, eArgRepeatOptional);
1834 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL);
1835 m_option_group.Finalize();
1838 ~CommandObjectBreakpointNameDelete() override = default;
1840 void
1841 HandleArgumentCompletion(CompletionRequest &request,
1842 OptionElementVector &opt_element_vector) override {
1843 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1844 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
1847 Options *GetOptions() override { return &m_option_group; }
1849 protected:
1850 void DoExecute(Args &command, CommandReturnObject &result) override {
1851 if (!m_name_options.m_name.OptionWasSet()) {
1852 result.AppendError("No name option provided.");
1853 return;
1856 Target &target =
1857 m_name_options.m_use_dummy ? GetDummyTarget() : GetTarget();
1859 std::unique_lock<std::recursive_mutex> lock;
1860 target.GetBreakpointList().GetListMutex(lock);
1862 const BreakpointList &breakpoints = target.GetBreakpointList();
1864 size_t num_breakpoints = breakpoints.GetSize();
1865 if (num_breakpoints == 0) {
1866 result.AppendError("No breakpoints, cannot delete names.");
1867 return;
1870 // Particular breakpoint selected; disable that breakpoint.
1871 BreakpointIDList valid_bp_ids;
1872 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1873 command, target, result, &valid_bp_ids,
1874 BreakpointName::Permissions::PermissionKinds::deletePerm);
1876 if (result.Succeeded()) {
1877 if (valid_bp_ids.GetSize() == 0) {
1878 result.AppendError("No breakpoints specified, cannot delete names.");
1879 return;
1881 ConstString bp_name(m_name_options.m_name.GetCurrentValue());
1882 size_t num_valid_ids = valid_bp_ids.GetSize();
1883 for (size_t index = 0; index < num_valid_ids; index++) {
1884 lldb::break_id_t bp_id =
1885 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID();
1886 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id);
1887 target.RemoveNameFromBreakpoint(bp_sp, bp_name);
1892 private:
1893 BreakpointNameOptionGroup m_name_options;
1894 OptionGroupOptions m_option_group;
1897 class CommandObjectBreakpointNameList : public CommandObjectParsed {
1898 public:
1899 CommandObjectBreakpointNameList(CommandInterpreter &interpreter)
1900 : CommandObjectParsed(interpreter, "list",
1901 "List either the names for a breakpoint or info "
1902 "about a given name. With no arguments, lists all "
1903 "names",
1904 "breakpoint name list <command-options>") {
1905 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL);
1906 m_option_group.Finalize();
1909 ~CommandObjectBreakpointNameList() override = default;
1911 Options *GetOptions() override { return &m_option_group; }
1913 protected:
1914 void DoExecute(Args &command, CommandReturnObject &result) override {
1915 Target &target =
1916 m_name_options.m_use_dummy ? GetDummyTarget() : GetTarget();
1918 std::vector<std::string> name_list;
1919 if (command.empty()) {
1920 target.GetBreakpointNames(name_list);
1921 } else {
1922 for (const Args::ArgEntry &arg : command) {
1923 name_list.push_back(arg.c_str());
1927 if (name_list.empty()) {
1928 result.AppendMessage("No breakpoint names found.");
1929 } else {
1930 for (const std::string &name_str : name_list) {
1931 const char *name = name_str.c_str();
1932 // First print out the options for the name:
1933 Status error;
1934 BreakpointName *bp_name =
1935 target.FindBreakpointName(ConstString(name), false, error);
1936 if (bp_name) {
1937 StreamString s;
1938 result.AppendMessageWithFormat("Name: %s\n", name);
1939 if (bp_name->GetDescription(&s, eDescriptionLevelFull)) {
1940 result.AppendMessage(s.GetString());
1943 std::unique_lock<std::recursive_mutex> lock;
1944 target.GetBreakpointList().GetListMutex(lock);
1946 BreakpointList &breakpoints = target.GetBreakpointList();
1947 bool any_set = false;
1948 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) {
1949 if (bp_sp->MatchesName(name)) {
1950 StreamString s;
1951 any_set = true;
1952 bp_sp->GetDescription(&s, eDescriptionLevelBrief);
1953 s.EOL();
1954 result.AppendMessage(s.GetString());
1957 if (!any_set)
1958 result.AppendMessage("No breakpoints using this name.");
1959 } else {
1960 result.AppendMessageWithFormat("Name: %s not found.\n", name);
1966 private:
1967 BreakpointNameOptionGroup m_name_options;
1968 OptionGroupOptions m_option_group;
1971 // CommandObjectBreakpointName
1972 class CommandObjectBreakpointName : public CommandObjectMultiword {
1973 public:
1974 CommandObjectBreakpointName(CommandInterpreter &interpreter)
1975 : CommandObjectMultiword(
1976 interpreter, "name", "Commands to manage breakpoint names") {
1979 SetHelpLong(
1981 Breakpoint names provide a general tagging mechanism for breakpoints. Each
1982 breakpoint name can be added to any number of breakpoints, and each breakpoint
1983 can have any number of breakpoint names attached to it. For instance:
1985 (lldb) break name add -N MyName 1-10
1987 adds the name MyName to breakpoints 1-10, and:
1989 (lldb) break set -n myFunc -N Name1 -N Name2
1991 adds two names to the breakpoint set at myFunc.
1993 They have a number of interrelated uses:
1995 1) They provide a stable way to refer to a breakpoint (e.g. in another
1996 breakpoint's action). Using the breakpoint ID for this purpose is fragile, since
1997 it depends on the order of breakpoint creation. Giving a name to the breakpoint
1998 you want to act on, and then referring to it by name, is more robust:
2000 (lldb) break set -n myFunc -N BKPT1
2001 (lldb) break set -n myOtherFunc -C "break disable BKPT1"
2003 2) This is actually just a specific use of a more general feature of breakpoint
2004 names. The <breakpt-id-list> argument type used to specify one or more
2005 breakpoints in most of the commands that deal with breakpoints also accepts
2006 breakpoint names. That allows you to refer to one breakpoint in a stable
2007 manner, but also makes them a convenient grouping mechanism, allowing you to
2008 easily act on a group of breakpoints by using their name, for instance disabling
2009 them all in one action:
2011 (lldb) break set -n myFunc -N Group1
2012 (lldb) break set -n myOtherFunc -N Group1
2013 (lldb) break disable Group1
2015 3) But breakpoint names are also entities in their own right, and can be
2016 configured with all the modifiable attributes of a breakpoint. Then when you
2017 add a breakpoint name to a breakpoint, the breakpoint will be configured to
2018 match the state of the breakpoint name. The link between the name and the
2019 breakpoints sharing it remains live, so if you change the configuration on the
2020 name, it will also change the configurations on the breakpoints:
2022 (lldb) break name configure -i 10 IgnoreSome
2023 (lldb) break set -n myFunc -N IgnoreSome
2024 (lldb) break list IgnoreSome
2025 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 10 enabled
2026 Names:
2027 IgnoreSome
2028 (lldb) break name configure -i 5 IgnoreSome
2029 (lldb) break list IgnoreSome
2030 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 5 enabled
2031 Names:
2032 IgnoreSome
2034 Options that are not configured on a breakpoint name don't affect the value of
2035 those options on the breakpoints they are added to. So for instance, if Name1
2036 has the -i option configured and Name2 the -c option, adding both names to a
2037 breakpoint will set the -i option from Name1 and the -c option from Name2, and
2038 the other options will be unaltered.
2040 If you add multiple names to a breakpoint which have configured values for
2041 the same option, the last name added's value wins.
2043 The "liveness" of these settings is one way, from name to breakpoint.
2044 If you use "break modify" to change an option that is also configured on a name
2045 which that breakpoint has, the "break modify" command will override the setting
2046 for that breakpoint, but won't change the value configured in the name or on the
2047 other breakpoints sharing that name.
2049 4) Breakpoint names are also a convenient way to copy option sets from one
2050 breakpoint to another. Using the -B option to "breakpoint name configure" makes
2051 a name configured with all the options of the original breakpoint. Then
2052 adding that name to another breakpoint copies over all the values from the
2053 original breakpoint to the new one.
2055 5) You can also use breakpoint names to hide breakpoints from the breakpoint
2056 operations that act on all breakpoints: "break delete", "break disable" and
2057 "break list". You do that by specifying a "false" value for the
2058 --allow-{list,delete,disable} options to "breakpoint name configure" and then
2059 adding that name to a breakpoint.
2061 This won't keep the breakpoint from being deleted or disabled if you refer to it
2062 specifically by ID. The point of the feature is to make sure users don't
2063 inadvertently delete or disable useful breakpoints (e.g. ones an IDE is using
2064 for its own purposes) as part of a "delete all" or "disable all" operation. The
2065 list hiding is because it's confusing for people to see breakpoints they
2066 didn't set.
2068 )");
2069 CommandObjectSP add_command_object(
2070 new CommandObjectBreakpointNameAdd(interpreter));
2071 CommandObjectSP delete_command_object(
2072 new CommandObjectBreakpointNameDelete(interpreter));
2073 CommandObjectSP list_command_object(
2074 new CommandObjectBreakpointNameList(interpreter));
2075 CommandObjectSP configure_command_object(
2076 new CommandObjectBreakpointNameConfigure(interpreter));
2078 LoadSubCommand("add", add_command_object);
2079 LoadSubCommand("delete", delete_command_object);
2080 LoadSubCommand("list", list_command_object);
2081 LoadSubCommand("configure", configure_command_object);
2084 ~CommandObjectBreakpointName() override = default;
2087 // CommandObjectBreakpointRead
2088 #pragma mark Read::CommandOptions
2089 #define LLDB_OPTIONS_breakpoint_read
2090 #include "CommandOptions.inc"
2092 #pragma mark Read
2094 class CommandObjectBreakpointRead : public CommandObjectParsed {
2095 public:
2096 CommandObjectBreakpointRead(CommandInterpreter &interpreter)
2097 : CommandObjectParsed(interpreter, "breakpoint read",
2098 "Read and set the breakpoints previously saved to "
2099 "a file with \"breakpoint write\". ",
2100 nullptr) {}
2102 ~CommandObjectBreakpointRead() override = default;
2104 Options *GetOptions() override { return &m_options; }
2106 class CommandOptions : public Options {
2107 public:
2108 CommandOptions() = default;
2110 ~CommandOptions() override = default;
2112 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2113 ExecutionContext *execution_context) override {
2114 Status error;
2115 const int short_option = m_getopt_table[option_idx].val;
2116 const char *long_option =
2117 m_getopt_table[option_idx].definition->long_option;
2119 switch (short_option) {
2120 case 'f':
2121 m_filename.assign(std::string(option_arg));
2122 break;
2123 case 'N': {
2124 Status name_error;
2125 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg),
2126 name_error)) {
2127 error = Status::FromError(CreateOptionParsingError(
2128 option_arg, short_option, long_option, name_error.AsCString()));
2130 m_names.push_back(std::string(option_arg));
2131 break;
2133 default:
2134 llvm_unreachable("Unimplemented option");
2137 return error;
2140 void OptionParsingStarting(ExecutionContext *execution_context) override {
2141 m_filename.clear();
2142 m_names.clear();
2145 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2146 return llvm::ArrayRef(g_breakpoint_read_options);
2149 void HandleOptionArgumentCompletion(
2150 CompletionRequest &request, OptionElementVector &opt_element_vector,
2151 int opt_element_index, CommandInterpreter &interpreter) override {
2152 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
2153 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
2155 switch (GetDefinitions()[opt_defs_index].short_option) {
2156 case 'f':
2157 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2158 interpreter, lldb::eDiskFileCompletion, request, nullptr);
2159 break;
2161 case 'N':
2162 std::optional<FileSpec> file_spec;
2163 const llvm::StringRef dash_f("-f");
2164 for (int arg_idx = 0; arg_idx < opt_arg_pos; arg_idx++) {
2165 if (dash_f == request.GetParsedLine().GetArgumentAtIndex(arg_idx)) {
2166 file_spec.emplace(
2167 request.GetParsedLine().GetArgumentAtIndex(arg_idx + 1));
2168 break;
2171 if (!file_spec)
2172 return;
2174 FileSystem::Instance().Resolve(*file_spec);
2175 Status error;
2176 StructuredData::ObjectSP input_data_sp =
2177 StructuredData::ParseJSONFromFile(*file_spec, error);
2178 if (!error.Success())
2179 return;
2181 StructuredData::Array *bkpt_array = input_data_sp->GetAsArray();
2182 if (!bkpt_array)
2183 return;
2185 const size_t num_bkpts = bkpt_array->GetSize();
2186 for (size_t i = 0; i < num_bkpts; i++) {
2187 StructuredData::ObjectSP bkpt_object_sp =
2188 bkpt_array->GetItemAtIndex(i);
2189 if (!bkpt_object_sp)
2190 return;
2192 StructuredData::Dictionary *bkpt_dict =
2193 bkpt_object_sp->GetAsDictionary();
2194 if (!bkpt_dict)
2195 return;
2197 StructuredData::ObjectSP bkpt_data_sp =
2198 bkpt_dict->GetValueForKey(Breakpoint::GetSerializationKey());
2199 if (!bkpt_data_sp)
2200 return;
2202 bkpt_dict = bkpt_data_sp->GetAsDictionary();
2203 if (!bkpt_dict)
2204 return;
2206 StructuredData::Array *names_array;
2208 if (!bkpt_dict->GetValueForKeyAsArray("Names", names_array))
2209 return;
2211 size_t num_names = names_array->GetSize();
2213 for (size_t i = 0; i < num_names; i++) {
2214 if (std::optional<llvm::StringRef> maybe_name =
2215 names_array->GetItemAtIndexAsString(i))
2216 request.TryCompleteCurrentArg(*maybe_name);
2222 std::string m_filename;
2223 std::vector<std::string> m_names;
2226 protected:
2227 void DoExecute(Args &command, CommandReturnObject &result) override {
2228 Target &target = GetTarget();
2230 std::unique_lock<std::recursive_mutex> lock;
2231 target.GetBreakpointList().GetListMutex(lock);
2233 FileSpec input_spec(m_options.m_filename);
2234 FileSystem::Instance().Resolve(input_spec);
2235 BreakpointIDList new_bps;
2236 Status error = target.CreateBreakpointsFromFile(input_spec,
2237 m_options.m_names, new_bps);
2239 if (!error.Success()) {
2240 result.AppendError(error.AsCString());
2241 return;
2244 Stream &output_stream = result.GetOutputStream();
2246 size_t num_breakpoints = new_bps.GetSize();
2247 if (num_breakpoints == 0) {
2248 result.AppendMessage("No breakpoints added.");
2249 } else {
2250 // No breakpoint selected; show info about all currently set breakpoints.
2251 result.AppendMessage("New breakpoints:");
2252 for (size_t i = 0; i < num_breakpoints; ++i) {
2253 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i);
2254 Breakpoint *bp = target.GetBreakpointList()
2255 .FindBreakpointByID(bp_id.GetBreakpointID())
2256 .get();
2257 if (bp)
2258 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial,
2259 false);
2264 private:
2265 CommandOptions m_options;
2268 // CommandObjectBreakpointWrite
2269 #pragma mark Write::CommandOptions
2270 #define LLDB_OPTIONS_breakpoint_write
2271 #include "CommandOptions.inc"
2273 #pragma mark Write
2274 class CommandObjectBreakpointWrite : public CommandObjectParsed {
2275 public:
2276 CommandObjectBreakpointWrite(CommandInterpreter &interpreter)
2277 : CommandObjectParsed(interpreter, "breakpoint write",
2278 "Write the breakpoints listed to a file that can "
2279 "be read in with \"breakpoint read\". "
2280 "If given no arguments, writes all breakpoints.",
2281 nullptr) {
2282 CommandObject::AddIDsArgumentData(eBreakpointArgs);
2285 ~CommandObjectBreakpointWrite() override = default;
2287 void
2288 HandleArgumentCompletion(CompletionRequest &request,
2289 OptionElementVector &opt_element_vector) override {
2290 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2291 GetCommandInterpreter(), lldb::eBreakpointCompletion, request, nullptr);
2294 Options *GetOptions() override { return &m_options; }
2296 class CommandOptions : public Options {
2297 public:
2298 CommandOptions() = default;
2300 ~CommandOptions() override = default;
2302 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2303 ExecutionContext *execution_context) override {
2304 Status error;
2305 const int short_option = m_getopt_table[option_idx].val;
2307 switch (short_option) {
2308 case 'f':
2309 m_filename.assign(std::string(option_arg));
2310 break;
2311 case 'a':
2312 m_append = true;
2313 break;
2314 default:
2315 llvm_unreachable("Unimplemented option");
2318 return error;
2321 void OptionParsingStarting(ExecutionContext *execution_context) override {
2322 m_filename.clear();
2323 m_append = false;
2326 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
2327 return llvm::ArrayRef(g_breakpoint_write_options);
2330 // Instance variables to hold the values for command options.
2332 std::string m_filename;
2333 bool m_append = false;
2336 protected:
2337 void DoExecute(Args &command, CommandReturnObject &result) override {
2338 Target &target = GetTarget();
2340 std::unique_lock<std::recursive_mutex> lock;
2341 target.GetBreakpointList().GetListMutex(lock);
2343 BreakpointIDList valid_bp_ids;
2344 if (!command.empty()) {
2345 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2346 command, target, result, &valid_bp_ids,
2347 BreakpointName::Permissions::PermissionKinds::listPerm);
2349 if (!result.Succeeded()) {
2350 result.SetStatus(eReturnStatusFailed);
2351 return;
2354 FileSpec file_spec(m_options.m_filename);
2355 FileSystem::Instance().Resolve(file_spec);
2356 Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids,
2357 m_options.m_append);
2358 if (!error.Success()) {
2359 result.AppendErrorWithFormat("error serializing breakpoints: %s.",
2360 error.AsCString());
2364 private:
2365 CommandOptions m_options;
2368 // CommandObjectMultiwordBreakpoint
2369 #pragma mark MultiwordBreakpoint
2371 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2372 CommandInterpreter &interpreter)
2373 : CommandObjectMultiword(
2374 interpreter, "breakpoint",
2375 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2376 "breakpoint <subcommand> [<command-options>]") {
2377 CommandObjectSP list_command_object(
2378 new CommandObjectBreakpointList(interpreter));
2379 CommandObjectSP enable_command_object(
2380 new CommandObjectBreakpointEnable(interpreter));
2381 CommandObjectSP disable_command_object(
2382 new CommandObjectBreakpointDisable(interpreter));
2383 CommandObjectSP clear_command_object(
2384 new CommandObjectBreakpointClear(interpreter));
2385 CommandObjectSP delete_command_object(
2386 new CommandObjectBreakpointDelete(interpreter));
2387 CommandObjectSP set_command_object(
2388 new CommandObjectBreakpointSet(interpreter));
2389 CommandObjectSP command_command_object(
2390 new CommandObjectBreakpointCommand(interpreter));
2391 CommandObjectSP modify_command_object(
2392 new CommandObjectBreakpointModify(interpreter));
2393 CommandObjectSP name_command_object(
2394 new CommandObjectBreakpointName(interpreter));
2395 CommandObjectSP write_command_object(
2396 new CommandObjectBreakpointWrite(interpreter));
2397 CommandObjectSP read_command_object(
2398 new CommandObjectBreakpointRead(interpreter));
2400 list_command_object->SetCommandName("breakpoint list");
2401 enable_command_object->SetCommandName("breakpoint enable");
2402 disable_command_object->SetCommandName("breakpoint disable");
2403 clear_command_object->SetCommandName("breakpoint clear");
2404 delete_command_object->SetCommandName("breakpoint delete");
2405 set_command_object->SetCommandName("breakpoint set");
2406 command_command_object->SetCommandName("breakpoint command");
2407 modify_command_object->SetCommandName("breakpoint modify");
2408 name_command_object->SetCommandName("breakpoint name");
2409 write_command_object->SetCommandName("breakpoint write");
2410 read_command_object->SetCommandName("breakpoint read");
2412 LoadSubCommand("list", list_command_object);
2413 LoadSubCommand("enable", enable_command_object);
2414 LoadSubCommand("disable", disable_command_object);
2415 LoadSubCommand("clear", clear_command_object);
2416 LoadSubCommand("delete", delete_command_object);
2417 LoadSubCommand("set", set_command_object);
2418 LoadSubCommand("command", command_command_object);
2419 LoadSubCommand("modify", modify_command_object);
2420 LoadSubCommand("name", name_command_object);
2421 LoadSubCommand("write", write_command_object);
2422 LoadSubCommand("read", read_command_object);
2425 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2427 void CommandObjectMultiwordBreakpoint::VerifyIDs(
2428 Args &args, Target &target, bool allow_locations,
2429 CommandReturnObject &result, BreakpointIDList *valid_ids,
2430 BreakpointName::Permissions ::PermissionKinds purpose) {
2431 // args can be strings representing 1). integers (for breakpoint ids)
2432 // 2). the full breakpoint & location
2433 // canonical representation
2434 // 3). the word "to" or a hyphen,
2435 // representing a range (in which case there
2436 // had *better* be an entry both before &
2437 // after of one of the first two types.
2438 // 4). A breakpoint name
2439 // If args is empty, we will use the last created breakpoint (if there is
2440 // one.)
2442 Args temp_args;
2444 if (args.empty()) {
2445 if (target.GetLastCreatedBreakpoint()) {
2446 valid_ids->AddBreakpointID(BreakpointID(
2447 target.GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID));
2448 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2449 } else {
2450 result.AppendError(
2451 "No breakpoint specified and no last created breakpoint.");
2453 return;
2456 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2457 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2458 // id range strings over; instead generate a list of strings for all the
2459 // breakpoint ids in the range, and shove all of those breakpoint id strings
2460 // into TEMP_ARGS.
2462 if (llvm::Error err = BreakpointIDList::FindAndReplaceIDRanges(
2463 args, &target, allow_locations, purpose, temp_args)) {
2464 result.SetError(std::move(err));
2465 return;
2467 result.SetStatus(eReturnStatusSuccessFinishNoResult);
2469 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2470 // BreakpointIDList:
2472 for (llvm::StringRef temp_arg : temp_args.GetArgumentArrayRef())
2473 if (auto bp_id = BreakpointID::ParseCanonicalReference(temp_arg))
2474 valid_ids->AddBreakpointID(*bp_id);
2476 // At this point, all of the breakpoint ids that the user passed in have
2477 // been converted to breakpoint IDs and put into valid_ids.
2479 // Now that we've converted everything from args into a list of breakpoint
2480 // ids, go through our tentative list of breakpoint id's and verify that
2481 // they correspond to valid/currently set breakpoints.
2483 const size_t count = valid_ids->GetSize();
2484 for (size_t i = 0; i < count; ++i) {
2485 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i);
2486 Breakpoint *breakpoint =
2487 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
2488 if (breakpoint != nullptr) {
2489 const size_t num_locations = breakpoint->GetNumLocations();
2490 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) {
2491 StreamString id_str;
2492 BreakpointID::GetCanonicalReference(
2493 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID());
2494 i = valid_ids->GetSize() + 1;
2495 result.AppendErrorWithFormat(
2496 "'%s' is not a currently valid breakpoint/location id.\n",
2497 id_str.GetData());
2499 } else {
2500 i = valid_ids->GetSize() + 1;
2501 result.AppendErrorWithFormat(
2502 "'%d' is not a currently valid breakpoint ID.\n",
2503 cur_bp_id.GetBreakpointID());