1 //===-- CommandObjectBreakpoint.cpp ---------------------------------------===//
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
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"
37 using namespace lldb_private
;
39 static void AddBreakpointDescription(Stream
*s
, Breakpoint
*bp
,
40 lldb::DescriptionLevel level
) {
42 bp
->GetDescription(s
, level
, true);
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
{
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
{
65 const int short_option
=
66 g_breakpoint_modify_options
[option_idx
].short_option
;
68 switch (short_option
) {
70 // Normally an empty breakpoint condition marks is as unset. But we need
71 // to say it was passed in.
72 m_bp_opts
.SetCondition(option_arg
.str().c_str());
73 m_bp_opts
.m_set_flags
.Set(BreakpointOptions::eCondition
);
76 m_commands
.push_back(std::string(option_arg
));
79 m_bp_opts
.SetEnabled(false);
82 m_bp_opts
.SetEnabled(true);
86 value
= OptionArgParser::ToBoolean(option_arg
, false, &success
);
88 m_bp_opts
.SetAutoContinue(value
);
90 error
.SetErrorStringWithFormat(
91 "invalid boolean value '%s' passed for -G option",
92 option_arg
.str().c_str());
95 uint32_t ignore_count
;
96 if (option_arg
.getAsInteger(0, ignore_count
))
97 error
.SetErrorStringWithFormat("invalid ignore count '%s'",
98 option_arg
.str().c_str());
100 m_bp_opts
.SetIgnoreCount(ignore_count
);
104 value
= OptionArgParser::ToBoolean(option_arg
, false, &success
);
106 m_bp_opts
.SetOneShot(value
);
108 error
.SetErrorStringWithFormat(
109 "invalid boolean value '%s' passed for -o option",
110 option_arg
.str().c_str());
113 lldb::tid_t thread_id
= LLDB_INVALID_THREAD_ID
;
114 if (option_arg
== "current") {
115 if (!execution_context
) {
116 error
.SetErrorStringWithFormat("No context to determine current "
119 ThreadSP ctx_thread_sp
= execution_context
->GetThreadSP();
120 if (!ctx_thread_sp
|| !ctx_thread_sp
->IsValid()) {
121 error
.SetErrorStringWithFormat("No currently selected thread");
123 thread_id
= ctx_thread_sp
->GetID();
126 } else if (option_arg
.getAsInteger(0, thread_id
)) {
127 error
.SetErrorStringWithFormat("invalid thread id string '%s'",
128 option_arg
.str().c_str());
130 if (thread_id
!= LLDB_INVALID_THREAD_ID
)
131 m_bp_opts
.SetThreadID(thread_id
);
134 m_bp_opts
.GetThreadSpec()->SetName(option_arg
.str().c_str());
137 m_bp_opts
.GetThreadSpec()->SetQueueName(option_arg
.str().c_str());
140 uint32_t thread_index
= UINT32_MAX
;
141 if (option_arg
.getAsInteger(0, thread_index
)) {
142 error
.SetErrorStringWithFormat("invalid thread index string '%s'",
143 option_arg
.str().c_str());
145 m_bp_opts
.GetThreadSpec()->SetIndex(thread_index
);
149 llvm_unreachable("Unimplemented option");
155 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
160 Status
OptionParsingFinished(ExecutionContext
*execution_context
) override
{
161 if (!m_commands
.empty()) {
162 auto cmd_data
= std::make_unique
<BreakpointOptions::CommandData
>();
164 for (std::string
&str
: m_commands
)
165 cmd_data
->user_source
.AppendString(str
);
167 cmd_data
->stop_on_error
= true;
168 m_bp_opts
.SetCommandDataCallback(cmd_data
);
173 const BreakpointOptions
&GetBreakpointOptions() { return m_bp_opts
; }
175 std::vector
<std::string
> m_commands
;
176 BreakpointOptions m_bp_opts
;
179 #define LLDB_OPTIONS_breakpoint_dummy
180 #include "CommandOptions.inc"
182 class BreakpointDummyOptionGroup
: public OptionGroup
{
184 BreakpointDummyOptionGroup() = default;
186 ~BreakpointDummyOptionGroup() override
= default;
188 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
189 return llvm::ArrayRef(g_breakpoint_dummy_options
);
192 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
193 ExecutionContext
*execution_context
) override
{
195 const int short_option
=
196 g_breakpoint_dummy_options
[option_idx
].short_option
;
198 switch (short_option
) {
203 llvm_unreachable("Unimplemented option");
209 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
216 #define LLDB_OPTIONS_breakpoint_set
217 #include "CommandOptions.inc"
219 // CommandObjectBreakpointSet
221 class CommandObjectBreakpointSet
: public CommandObjectParsed
{
223 enum BreakpointSetType
{
227 eSetTypeFunctionName
,
228 eSetTypeFunctionRegexp
,
229 eSetTypeSourceRegexp
,
234 CommandObjectBreakpointSet(CommandInterpreter
&interpreter
)
235 : CommandObjectParsed(
236 interpreter
, "breakpoint set",
237 "Sets a breakpoint or set of breakpoints in the executable.",
238 "breakpoint set <cmd-options>"),
239 m_python_class_options("scripted breakpoint", true, 'P') {
240 // We're picking up all the normal options, commands and disable.
241 m_all_options
.Append(&m_python_class_options
,
242 LLDB_OPT_SET_1
| LLDB_OPT_SET_2
, LLDB_OPT_SET_11
);
243 m_all_options
.Append(&m_bp_opts
,
244 LLDB_OPT_SET_1
| LLDB_OPT_SET_3
| LLDB_OPT_SET_4
,
246 m_all_options
.Append(&m_dummy_options
, LLDB_OPT_SET_1
, LLDB_OPT_SET_ALL
);
247 m_all_options
.Append(&m_options
);
248 m_all_options
.Finalize();
251 ~CommandObjectBreakpointSet() override
= default;
253 Options
*GetOptions() override
{ return &m_all_options
; }
255 class CommandOptions
: public OptionGroup
{
257 CommandOptions() = default;
259 ~CommandOptions() override
= default;
261 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
262 ExecutionContext
*execution_context
) override
{
264 const int short_option
=
265 g_breakpoint_set_options
[option_idx
].short_option
;
267 switch (short_option
) {
269 m_load_addr
= OptionArgParser::ToAddress(execution_context
, option_arg
,
270 LLDB_INVALID_ADDRESS
, &error
);
278 m_func_names
.push_back(std::string(option_arg
));
279 m_func_name_type_mask
|= eFunctionNameTypeBase
;
283 if (option_arg
.getAsInteger(0, m_column
))
284 error
.SetErrorStringWithFormat("invalid column number: %s",
285 option_arg
.str().c_str());
289 LanguageType language
= Language::GetLanguageTypeFromString(option_arg
);
292 case eLanguageTypeC89
:
294 case eLanguageTypeC99
:
295 case eLanguageTypeC11
:
296 m_exception_language
= eLanguageTypeC
;
298 case eLanguageTypeC_plus_plus
:
299 case eLanguageTypeC_plus_plus_03
:
300 case eLanguageTypeC_plus_plus_11
:
301 case eLanguageTypeC_plus_plus_14
:
302 m_exception_language
= eLanguageTypeC_plus_plus
;
304 case eLanguageTypeObjC
:
305 m_exception_language
= eLanguageTypeObjC
;
307 case eLanguageTypeObjC_plus_plus
:
308 error
.SetErrorStringWithFormat(
309 "Set exception breakpoints separately for c++ and objective-c");
311 case eLanguageTypeUnknown
:
312 error
.SetErrorStringWithFormat(
313 "Unknown language type: '%s' for exception breakpoint",
314 option_arg
.str().c_str());
317 error
.SetErrorStringWithFormat(
318 "Unsupported language type: '%s' for exception breakpoint",
319 option_arg
.str().c_str());
324 m_filenames
.AppendIfUnique(FileSpec(option_arg
));
328 m_func_names
.push_back(std::string(option_arg
));
329 m_func_name_type_mask
|= eFunctionNameTypeFull
;
334 m_catch_bp
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
336 error
.SetErrorStringWithFormat(
337 "Invalid boolean value for on-catch option: '%s'",
338 option_arg
.str().c_str());
348 value
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
350 m_skip_prologue
= eLazyBoolYes
;
352 m_skip_prologue
= eLazyBoolNo
;
355 error
.SetErrorStringWithFormat(
356 "Invalid boolean value for skip prologue option: '%s'",
357 option_arg
.str().c_str());
361 if (option_arg
.getAsInteger(0, m_line_num
))
362 error
.SetErrorStringWithFormat("invalid line number: %s.",
363 option_arg
.str().c_str());
367 m_language
= Language::GetLanguageTypeFromString(option_arg
);
368 if (m_language
== eLanguageTypeUnknown
)
369 error
.SetErrorStringWithFormat(
370 "Unknown language type: '%s' for breakpoint",
371 option_arg
.str().c_str());
377 value
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
379 m_move_to_nearest_code
= eLazyBoolYes
;
381 m_move_to_nearest_code
= eLazyBoolNo
;
384 error
.SetErrorStringWithFormat(
385 "Invalid boolean value for move-to-nearest-code option: '%s'",
386 option_arg
.str().c_str());
391 m_func_names
.push_back(std::string(option_arg
));
392 m_func_name_type_mask
|= eFunctionNameTypeMethod
;
396 m_func_names
.push_back(std::string(option_arg
));
397 m_func_name_type_mask
|= eFunctionNameTypeAuto
;
401 if (BreakpointID::StringIsBreakpointName(option_arg
, error
))
402 m_breakpoint_names
.push_back(std::string(option_arg
));
404 error
.SetErrorStringWithFormat("Invalid breakpoint name: %s",
405 option_arg
.str().c_str());
410 lldb::addr_t tmp_offset_addr
;
411 tmp_offset_addr
= OptionArgParser::ToAddress(execution_context
,
412 option_arg
, 0, &error
);
414 m_offset_addr
= tmp_offset_addr
;
418 m_exception_extra_args
.AppendArgument("-O");
419 m_exception_extra_args
.AppendArgument(option_arg
);
423 m_source_text_regexp
.assign(std::string(option_arg
));
427 m_func_regexp
.assign(std::string(option_arg
));
431 m_modules
.AppendIfUnique(FileSpec(option_arg
));
435 m_func_names
.push_back(std::string(option_arg
));
436 m_func_name_type_mask
|= eFunctionNameTypeSelector
;
441 m_throw_bp
= OptionArgParser::ToBoolean(option_arg
, true, &success
);
443 error
.SetErrorStringWithFormat(
444 "Invalid boolean value for on-throw option: '%s'",
445 option_arg
.str().c_str());
449 m_source_regex_func_names
.insert(std::string(option_arg
));
454 OptionValueFileColonLine value
;
455 Status fcl_err
= value
.SetValueFromString(option_arg
);
456 if (!fcl_err
.Success()) {
457 error
.SetErrorStringWithFormat(
458 "Invalid value for file:line specifier: %s",
459 fcl_err
.AsCString());
461 m_filenames
.AppendIfUnique(value
.GetFileSpec());
462 m_line_num
= value
.GetLineNumber();
463 m_column
= value
.GetColumnNumber();
468 llvm_unreachable("Unimplemented option");
474 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
478 m_func_names
.clear();
479 m_func_name_type_mask
= eFunctionNameTypeNone
;
480 m_func_regexp
.clear();
481 m_source_text_regexp
.clear();
483 m_load_addr
= LLDB_INVALID_ADDRESS
;
488 m_exception_language
= eLanguageTypeUnknown
;
489 m_language
= lldb::eLanguageTypeUnknown
;
490 m_skip_prologue
= eLazyBoolCalculate
;
491 m_breakpoint_names
.clear();
493 m_exception_extra_args
.Clear();
494 m_move_to_nearest_code
= eLazyBoolCalculate
;
495 m_source_regex_func_names
.clear();
496 m_current_key
.clear();
499 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
500 return llvm::ArrayRef(g_breakpoint_set_options
);
503 // Instance variables to hold the values for command options.
505 std::string m_condition
;
506 FileSpecList m_filenames
;
507 uint32_t m_line_num
= 0;
508 uint32_t m_column
= 0;
509 std::vector
<std::string
> m_func_names
;
510 std::vector
<std::string
> m_breakpoint_names
;
511 lldb::FunctionNameType m_func_name_type_mask
= eFunctionNameTypeNone
;
512 std::string m_func_regexp
;
513 std::string m_source_text_regexp
;
514 FileSpecList m_modules
;
515 lldb::addr_t m_load_addr
= 0;
516 lldb::addr_t m_offset_addr
;
517 bool m_catch_bp
= false;
518 bool m_throw_bp
= true;
519 bool m_hardware
= false; // Request to use hardware breakpoints
520 lldb::LanguageType m_exception_language
= eLanguageTypeUnknown
;
521 lldb::LanguageType m_language
= lldb::eLanguageTypeUnknown
;
522 LazyBool m_skip_prologue
= eLazyBoolCalculate
;
523 bool m_all_files
= false;
524 Args m_exception_extra_args
;
525 LazyBool m_move_to_nearest_code
= eLazyBoolCalculate
;
526 std::unordered_set
<std::string
> m_source_regex_func_names
;
527 std::string m_current_key
;
531 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
532 Target
&target
= GetSelectedOrDummyTarget(m_dummy_options
.m_use_dummy
);
534 // The following are the various types of breakpoints that could be set:
535 // 1). -f -l -p [-s -g] (setting breakpoint by source location)
536 // 2). -a [-s -g] (setting breakpoint by address)
537 // 3). -n [-s -g] (setting breakpoint by function name)
538 // 4). -r [-s -g] (setting breakpoint by function name regular
540 // 5). -p -f (setting a breakpoint by comparing a reg-exp
542 // 6). -E [-w -h] (setting a breakpoint for exceptions for a
545 BreakpointSetType break_type
= eSetTypeInvalid
;
547 if (!m_python_class_options
.GetName().empty())
548 break_type
= eSetTypeScripted
;
549 else if (m_options
.m_line_num
!= 0)
550 break_type
= eSetTypeFileAndLine
;
551 else if (m_options
.m_load_addr
!= LLDB_INVALID_ADDRESS
)
552 break_type
= eSetTypeAddress
;
553 else if (!m_options
.m_func_names
.empty())
554 break_type
= eSetTypeFunctionName
;
555 else if (!m_options
.m_func_regexp
.empty())
556 break_type
= eSetTypeFunctionRegexp
;
557 else if (!m_options
.m_source_text_regexp
.empty())
558 break_type
= eSetTypeSourceRegexp
;
559 else if (m_options
.m_exception_language
!= eLanguageTypeUnknown
)
560 break_type
= eSetTypeException
;
562 BreakpointSP bp_sp
= nullptr;
563 FileSpec module_spec
;
564 const bool internal
= false;
566 // If the user didn't specify skip-prologue, having an offset should turn
568 if (m_options
.m_offset_addr
!= 0 &&
569 m_options
.m_skip_prologue
== eLazyBoolCalculate
)
570 m_options
.m_skip_prologue
= eLazyBoolNo
;
572 switch (break_type
) {
573 case eSetTypeFileAndLine
: // Breakpoint by source position
576 const size_t num_files
= m_options
.m_filenames
.GetSize();
577 if (num_files
== 0) {
578 if (!GetDefaultFile(target
, file
, result
)) {
579 result
.AppendError("No file supplied and no default file available.");
582 } else if (num_files
> 1) {
583 result
.AppendError("Only one file at a time is allowed for file and "
584 "line breakpoints.");
587 file
= m_options
.m_filenames
.GetFileSpecAtIndex(0);
589 // Only check for inline functions if
590 LazyBool check_inlines
= eLazyBoolCalculate
;
592 bp_sp
= target
.CreateBreakpoint(
593 &(m_options
.m_modules
), file
, m_options
.m_line_num
,
594 m_options
.m_column
, m_options
.m_offset_addr
, check_inlines
,
595 m_options
.m_skip_prologue
, internal
, m_options
.m_hardware
,
596 m_options
.m_move_to_nearest_code
);
599 case eSetTypeAddress
: // Breakpoint by address
601 // If a shared library has been specified, make an lldb_private::Address
602 // with the library, and use that. That way the address breakpoint
603 // will track the load location of the library.
604 size_t num_modules_specified
= m_options
.m_modules
.GetSize();
605 if (num_modules_specified
== 1) {
606 const FileSpec
&file_spec
=
607 m_options
.m_modules
.GetFileSpecAtIndex(0);
608 bp_sp
= target
.CreateAddressInModuleBreakpoint(
609 m_options
.m_load_addr
, internal
, file_spec
, m_options
.m_hardware
);
610 } else if (num_modules_specified
== 0) {
611 bp_sp
= target
.CreateBreakpoint(m_options
.m_load_addr
, internal
,
612 m_options
.m_hardware
);
614 result
.AppendError("Only one shared library can be specified for "
615 "address breakpoints.");
620 case eSetTypeFunctionName
: // Breakpoint by function name
622 FunctionNameType name_type_mask
= m_options
.m_func_name_type_mask
;
624 if (name_type_mask
== 0)
625 name_type_mask
= eFunctionNameTypeAuto
;
627 bp_sp
= target
.CreateBreakpoint(
628 &(m_options
.m_modules
), &(m_options
.m_filenames
),
629 m_options
.m_func_names
, name_type_mask
, m_options
.m_language
,
630 m_options
.m_offset_addr
, m_options
.m_skip_prologue
, internal
,
631 m_options
.m_hardware
);
634 case eSetTypeFunctionRegexp
: // Breakpoint by regular expression function
637 RegularExpression
regexp(m_options
.m_func_regexp
);
638 if (llvm::Error err
= regexp
.GetError()) {
639 result
.AppendErrorWithFormat(
640 "Function name regular expression could not be compiled: %s",
641 llvm::toString(std::move(err
)).c_str());
642 // Check if the incorrect regex looks like a globbing expression and
643 // warn the user about it.
644 if (!m_options
.m_func_regexp
.empty()) {
645 if (m_options
.m_func_regexp
[0] == '*' ||
646 m_options
.m_func_regexp
[0] == '?')
647 result
.AppendWarning(
648 "Function name regex does not accept glob patterns.");
653 bp_sp
= target
.CreateFuncRegexBreakpoint(
654 &(m_options
.m_modules
), &(m_options
.m_filenames
), std::move(regexp
),
655 m_options
.m_language
, m_options
.m_skip_prologue
, internal
,
656 m_options
.m_hardware
);
658 case eSetTypeSourceRegexp
: // Breakpoint by regexp on source text.
660 const size_t num_files
= m_options
.m_filenames
.GetSize();
662 if (num_files
== 0 && !m_options
.m_all_files
) {
664 if (!GetDefaultFile(target
, file
, result
)) {
666 "No files provided and could not find default file.");
669 m_options
.m_filenames
.Append(file
);
673 RegularExpression
regexp(m_options
.m_source_text_regexp
);
674 if (llvm::Error err
= regexp
.GetError()) {
675 result
.AppendErrorWithFormat(
676 "Source text regular expression could not be compiled: \"%s\"",
677 llvm::toString(std::move(err
)).c_str());
680 bp_sp
= target
.CreateSourceRegexBreakpoint(
681 &(m_options
.m_modules
), &(m_options
.m_filenames
),
682 m_options
.m_source_regex_func_names
, std::move(regexp
), internal
,
683 m_options
.m_hardware
, m_options
.m_move_to_nearest_code
);
685 case eSetTypeException
: {
686 Status precond_error
;
687 bp_sp
= target
.CreateExceptionBreakpoint(
688 m_options
.m_exception_language
, m_options
.m_catch_bp
,
689 m_options
.m_throw_bp
, internal
, &m_options
.m_exception_extra_args
,
691 if (precond_error
.Fail()) {
692 result
.AppendErrorWithFormat(
693 "Error setting extra exception arguments: %s",
694 precond_error
.AsCString());
695 target
.RemoveBreakpointByID(bp_sp
->GetID());
699 case eSetTypeScripted
: {
702 bp_sp
= target
.CreateScriptedBreakpoint(
703 m_python_class_options
.GetName().c_str(), &(m_options
.m_modules
),
704 &(m_options
.m_filenames
), false, m_options
.m_hardware
,
705 m_python_class_options
.GetStructuredData(), &error
);
707 result
.AppendErrorWithFormat(
708 "Error setting extra exception arguments: %s", error
.AsCString());
709 target
.RemoveBreakpointByID(bp_sp
->GetID());
717 // Now set the various options that were passed in:
719 bp_sp
->GetOptions().CopyOverSetOptions(m_bp_opts
.GetBreakpointOptions());
721 if (!m_options
.m_breakpoint_names
.empty()) {
723 for (auto name
: m_options
.m_breakpoint_names
) {
724 target
.AddNameToBreakpoint(bp_sp
, name
.c_str(), name_error
);
725 if (name_error
.Fail()) {
726 result
.AppendErrorWithFormat("Invalid breakpoint name: %s",
728 target
.RemoveBreakpointByID(bp_sp
->GetID());
736 Stream
&output_stream
= result
.GetOutputStream();
737 const bool show_locations
= false;
738 bp_sp
->GetDescription(&output_stream
, lldb::eDescriptionLevelInitial
,
740 if (&target
== &GetDummyTarget())
741 output_stream
.Printf("Breakpoint set in dummy target, will get copied "
742 "into future targets.\n");
744 // Don't print out this warning for exception breakpoints. They can
745 // get set before the target is set, but we won't know how to actually
746 // set the breakpoint till we run.
747 if (bp_sp
->GetNumLocations() == 0 && break_type
!= eSetTypeException
) {
748 output_stream
.Printf("WARNING: Unable to resolve breakpoint to any "
749 "actual locations.\n");
752 result
.SetStatus(eReturnStatusSuccessFinishResult
);
754 result
.AppendError("Breakpoint creation failed: No breakpoint created.");
759 bool GetDefaultFile(Target
&target
, FileSpec
&file
,
760 CommandReturnObject
&result
) {
761 uint32_t default_line
;
762 // First use the Source Manager's default file. Then use the current stack
764 if (!target
.GetSourceManager().GetDefaultFileAndLine(file
, default_line
)) {
765 StackFrame
*cur_frame
= m_exe_ctx
.GetFramePtr();
766 if (cur_frame
== nullptr) {
768 "No selected frame to use to find the default file.");
770 } else if (!cur_frame
->HasDebugInformation()) {
771 result
.AppendError("Cannot use the selected frame to find the default "
772 "file, it has no debug info.");
775 const SymbolContext
&sc
=
776 cur_frame
->GetSymbolContext(eSymbolContextLineEntry
);
777 if (sc
.line_entry
.file
) {
778 file
= sc
.line_entry
.file
;
780 result
.AppendError("Can't find the file for the selected frame to "
781 "use as the default file.");
789 BreakpointOptionGroup m_bp_opts
;
790 BreakpointDummyOptionGroup m_dummy_options
;
791 OptionGroupPythonClassWithDict m_python_class_options
;
792 CommandOptions m_options
;
793 OptionGroupOptions m_all_options
;
796 // CommandObjectBreakpointModify
799 class CommandObjectBreakpointModify
: public CommandObjectParsed
{
801 CommandObjectBreakpointModify(CommandInterpreter
&interpreter
)
802 : CommandObjectParsed(interpreter
, "breakpoint modify",
803 "Modify the options on a breakpoint or set of "
804 "breakpoints in the executable. "
805 "If no breakpoint is specified, acts on the last "
806 "created breakpoint. "
807 "With the exception of -e, -d and -i, passing an "
808 "empty argument clears the modification.",
810 CommandArgumentEntry arg
;
811 CommandObject::AddIDsArgumentData(arg
, eArgTypeBreakpointID
,
812 eArgTypeBreakpointIDRange
);
813 // Add the entry for the first argument for this command to the object's
815 m_arguments
.push_back(arg
);
817 m_options
.Append(&m_bp_opts
,
818 LLDB_OPT_SET_1
| LLDB_OPT_SET_2
| LLDB_OPT_SET_3
,
820 m_options
.Append(&m_dummy_opts
, LLDB_OPT_SET_1
, LLDB_OPT_SET_ALL
);
821 m_options
.Finalize();
824 ~CommandObjectBreakpointModify() override
= default;
827 HandleArgumentCompletion(CompletionRequest
&request
,
828 OptionElementVector
&opt_element_vector
) override
{
829 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
830 GetCommandInterpreter(), lldb::eBreakpointCompletion
, request
, nullptr);
833 Options
*GetOptions() override
{ return &m_options
; }
836 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
837 Target
&target
= GetSelectedOrDummyTarget(m_dummy_opts
.m_use_dummy
);
839 std::unique_lock
<std::recursive_mutex
> lock
;
840 target
.GetBreakpointList().GetListMutex(lock
);
842 BreakpointIDList valid_bp_ids
;
844 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
845 command
, &target
, result
, &valid_bp_ids
,
846 BreakpointName::Permissions::PermissionKinds::disablePerm
);
848 if (result
.Succeeded()) {
849 const size_t count
= valid_bp_ids
.GetSize();
850 for (size_t i
= 0; i
< count
; ++i
) {
851 BreakpointID cur_bp_id
= valid_bp_ids
.GetBreakpointIDAtIndex(i
);
853 if (cur_bp_id
.GetBreakpointID() != LLDB_INVALID_BREAK_ID
) {
855 target
.GetBreakpointByID(cur_bp_id
.GetBreakpointID()).get();
856 if (cur_bp_id
.GetLocationID() != LLDB_INVALID_BREAK_ID
) {
857 BreakpointLocation
*location
=
858 bp
->FindLocationByID(cur_bp_id
.GetLocationID()).get();
860 location
->GetLocationOptions().CopyOverSetOptions(
861 m_bp_opts
.GetBreakpointOptions());
863 bp
->GetOptions().CopyOverSetOptions(
864 m_bp_opts
.GetBreakpointOptions());
872 BreakpointOptionGroup m_bp_opts
;
873 BreakpointDummyOptionGroup m_dummy_opts
;
874 OptionGroupOptions m_options
;
877 // CommandObjectBreakpointEnable
880 class CommandObjectBreakpointEnable
: public CommandObjectParsed
{
882 CommandObjectBreakpointEnable(CommandInterpreter
&interpreter
)
883 : CommandObjectParsed(interpreter
, "enable",
884 "Enable the specified disabled breakpoint(s). If "
885 "no breakpoints are specified, enable all of them.",
887 CommandArgumentEntry arg
;
888 CommandObject::AddIDsArgumentData(arg
, eArgTypeBreakpointID
,
889 eArgTypeBreakpointIDRange
);
890 // Add the entry for the first argument for this command to the object's
892 m_arguments
.push_back(arg
);
895 ~CommandObjectBreakpointEnable() override
= default;
898 HandleArgumentCompletion(CompletionRequest
&request
,
899 OptionElementVector
&opt_element_vector
) override
{
900 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
901 GetCommandInterpreter(), lldb::eBreakpointCompletion
, request
, nullptr);
905 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
906 Target
&target
= GetSelectedOrDummyTarget();
908 std::unique_lock
<std::recursive_mutex
> lock
;
909 target
.GetBreakpointList().GetListMutex(lock
);
911 const BreakpointList
&breakpoints
= target
.GetBreakpointList();
913 size_t num_breakpoints
= breakpoints
.GetSize();
915 if (num_breakpoints
== 0) {
916 result
.AppendError("No breakpoints exist to be enabled.");
920 if (command
.empty()) {
921 // No breakpoint selected; enable all currently set breakpoints.
922 target
.EnableAllowedBreakpoints();
923 result
.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64
925 (uint64_t)num_breakpoints
);
926 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
928 // Particular breakpoint selected; enable that breakpoint.
929 BreakpointIDList valid_bp_ids
;
930 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
931 command
, &target
, result
, &valid_bp_ids
,
932 BreakpointName::Permissions::PermissionKinds::disablePerm
);
934 if (result
.Succeeded()) {
935 int enable_count
= 0;
937 const size_t count
= valid_bp_ids
.GetSize();
938 for (size_t i
= 0; i
< count
; ++i
) {
939 BreakpointID cur_bp_id
= valid_bp_ids
.GetBreakpointIDAtIndex(i
);
941 if (cur_bp_id
.GetBreakpointID() != LLDB_INVALID_BREAK_ID
) {
942 Breakpoint
*breakpoint
=
943 target
.GetBreakpointByID(cur_bp_id
.GetBreakpointID()).get();
944 if (cur_bp_id
.GetLocationID() != LLDB_INVALID_BREAK_ID
) {
945 BreakpointLocation
*location
=
946 breakpoint
->FindLocationByID(cur_bp_id
.GetLocationID()).get();
948 location
->SetEnabled(true);
952 breakpoint
->SetEnabled(true);
957 result
.AppendMessageWithFormat("%d breakpoints enabled.\n",
958 enable_count
+ loc_count
);
959 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
965 // CommandObjectBreakpointDisable
968 class CommandObjectBreakpointDisable
: public CommandObjectParsed
{
970 CommandObjectBreakpointDisable(CommandInterpreter
&interpreter
)
971 : CommandObjectParsed(
972 interpreter
, "breakpoint disable",
973 "Disable the specified breakpoint(s) without deleting "
974 "them. If none are specified, disable all "
978 "Disable the specified breakpoint(s) without deleting them. \
979 If none are specified, disable all breakpoints."
983 "Note: disabling a breakpoint will cause none of its locations to be hit \
984 regardless of whether individual locations are enabled or disabled. After the sequence:"
987 (lldb) break disable 1
988 (lldb) break enable 1.1
990 execution will NOT stop at location 1.1. To achieve that, type:
992 (lldb) break disable 1.*
993 (lldb) break enable 1.1
996 "The first command disables all locations for breakpoint 1, \
997 the second re-enables the first location.");
999 CommandArgumentEntry arg
;
1000 CommandObject::AddIDsArgumentData(arg
, eArgTypeBreakpointID
,
1001 eArgTypeBreakpointIDRange
);
1002 // Add the entry for the first argument for this command to the object's
1003 // arguments vector.
1004 m_arguments
.push_back(arg
);
1007 ~CommandObjectBreakpointDisable() override
= default;
1010 HandleArgumentCompletion(CompletionRequest
&request
,
1011 OptionElementVector
&opt_element_vector
) override
{
1012 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1013 GetCommandInterpreter(), lldb::eBreakpointCompletion
, request
, nullptr);
1017 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1018 Target
&target
= GetSelectedOrDummyTarget();
1019 std::unique_lock
<std::recursive_mutex
> lock
;
1020 target
.GetBreakpointList().GetListMutex(lock
);
1022 const BreakpointList
&breakpoints
= target
.GetBreakpointList();
1023 size_t num_breakpoints
= breakpoints
.GetSize();
1025 if (num_breakpoints
== 0) {
1026 result
.AppendError("No breakpoints exist to be disabled.");
1030 if (command
.empty()) {
1031 // No breakpoint selected; disable all currently set breakpoints.
1032 target
.DisableAllowedBreakpoints();
1033 result
.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64
1035 (uint64_t)num_breakpoints
);
1036 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1038 // Particular breakpoint selected; disable that breakpoint.
1039 BreakpointIDList valid_bp_ids
;
1041 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1042 command
, &target
, result
, &valid_bp_ids
,
1043 BreakpointName::Permissions::PermissionKinds::disablePerm
);
1045 if (result
.Succeeded()) {
1046 int disable_count
= 0;
1048 const size_t count
= valid_bp_ids
.GetSize();
1049 for (size_t i
= 0; i
< count
; ++i
) {
1050 BreakpointID cur_bp_id
= valid_bp_ids
.GetBreakpointIDAtIndex(i
);
1052 if (cur_bp_id
.GetBreakpointID() != LLDB_INVALID_BREAK_ID
) {
1053 Breakpoint
*breakpoint
=
1054 target
.GetBreakpointByID(cur_bp_id
.GetBreakpointID()).get();
1055 if (cur_bp_id
.GetLocationID() != LLDB_INVALID_BREAK_ID
) {
1056 BreakpointLocation
*location
=
1057 breakpoint
->FindLocationByID(cur_bp_id
.GetLocationID()).get();
1059 location
->SetEnabled(false);
1063 breakpoint
->SetEnabled(false);
1068 result
.AppendMessageWithFormat("%d breakpoints disabled.\n",
1069 disable_count
+ loc_count
);
1070 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1076 // CommandObjectBreakpointList
1078 #pragma mark List::CommandOptions
1079 #define LLDB_OPTIONS_breakpoint_list
1080 #include "CommandOptions.inc"
1084 class CommandObjectBreakpointList
: public CommandObjectParsed
{
1086 CommandObjectBreakpointList(CommandInterpreter
&interpreter
)
1087 : CommandObjectParsed(
1088 interpreter
, "breakpoint list",
1089 "List some or all breakpoints at configurable levels of detail.",
1091 CommandArgumentEntry arg
;
1092 CommandArgumentData bp_id_arg
;
1094 // Define the first (and only) variant of this arg.
1095 bp_id_arg
.arg_type
= eArgTypeBreakpointID
;
1096 bp_id_arg
.arg_repetition
= eArgRepeatOptional
;
1098 // There is only one variant this argument could be; put it into the
1100 arg
.push_back(bp_id_arg
);
1102 // Push the data for the first argument into the m_arguments vector.
1103 m_arguments
.push_back(arg
);
1106 ~CommandObjectBreakpointList() override
= default;
1108 Options
*GetOptions() override
{ return &m_options
; }
1110 class CommandOptions
: public Options
{
1112 CommandOptions() = default;
1114 ~CommandOptions() override
= default;
1116 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1117 ExecutionContext
*execution_context
) override
{
1119 const int short_option
= m_getopt_table
[option_idx
].val
;
1121 switch (short_option
) {
1123 m_level
= lldb::eDescriptionLevelBrief
;
1129 m_level
= lldb::eDescriptionLevelFull
;
1132 m_level
= lldb::eDescriptionLevelVerbose
;
1138 llvm_unreachable("Unimplemented option");
1144 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1145 m_level
= lldb::eDescriptionLevelFull
;
1147 m_use_dummy
= false;
1150 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1151 return llvm::ArrayRef(g_breakpoint_list_options
);
1154 // Instance variables to hold the values for command options.
1156 lldb::DescriptionLevel m_level
= lldb::eDescriptionLevelBrief
;
1159 bool m_use_dummy
= false;
1163 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1164 Target
&target
= GetSelectedOrDummyTarget(m_options
.m_use_dummy
);
1166 const BreakpointList
&breakpoints
=
1167 target
.GetBreakpointList(m_options
.m_internal
);
1168 std::unique_lock
<std::recursive_mutex
> lock
;
1169 target
.GetBreakpointList(m_options
.m_internal
).GetListMutex(lock
);
1171 size_t num_breakpoints
= breakpoints
.GetSize();
1173 if (num_breakpoints
== 0) {
1174 result
.AppendMessage("No breakpoints currently set.");
1175 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1179 Stream
&output_stream
= result
.GetOutputStream();
1181 if (command
.empty()) {
1182 // No breakpoint selected; show info about all currently set breakpoints.
1183 result
.AppendMessage("Current breakpoints:");
1184 for (size_t i
= 0; i
< num_breakpoints
; ++i
) {
1185 Breakpoint
*breakpoint
= breakpoints
.GetBreakpointAtIndex(i
).get();
1186 if (breakpoint
->AllowList())
1187 AddBreakpointDescription(&output_stream
, breakpoint
,
1190 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1192 // Particular breakpoints selected; show info about that breakpoint.
1193 BreakpointIDList valid_bp_ids
;
1194 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1195 command
, &target
, result
, &valid_bp_ids
,
1196 BreakpointName::Permissions::PermissionKinds::listPerm
);
1198 if (result
.Succeeded()) {
1199 for (size_t i
= 0; i
< valid_bp_ids
.GetSize(); ++i
) {
1200 BreakpointID cur_bp_id
= valid_bp_ids
.GetBreakpointIDAtIndex(i
);
1201 Breakpoint
*breakpoint
=
1202 target
.GetBreakpointByID(cur_bp_id
.GetBreakpointID()).get();
1203 AddBreakpointDescription(&output_stream
, breakpoint
,
1206 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1208 result
.AppendError("Invalid breakpoint ID.");
1214 CommandOptions m_options
;
1217 // CommandObjectBreakpointClear
1218 #pragma mark Clear::CommandOptions
1220 #define LLDB_OPTIONS_breakpoint_clear
1221 #include "CommandOptions.inc"
1225 class CommandObjectBreakpointClear
: public CommandObjectParsed
{
1227 enum BreakpointClearType
{ eClearTypeInvalid
, eClearTypeFileAndLine
};
1229 CommandObjectBreakpointClear(CommandInterpreter
&interpreter
)
1230 : CommandObjectParsed(interpreter
, "breakpoint clear",
1231 "Delete or disable breakpoints matching the "
1232 "specified source file and line.",
1233 "breakpoint clear <cmd-options>") {}
1235 ~CommandObjectBreakpointClear() override
= default;
1237 Options
*GetOptions() override
{ return &m_options
; }
1239 class CommandOptions
: public Options
{
1241 CommandOptions() = default;
1243 ~CommandOptions() override
= default;
1245 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1246 ExecutionContext
*execution_context
) override
{
1248 const int short_option
= m_getopt_table
[option_idx
].val
;
1250 switch (short_option
) {
1252 m_filename
.assign(std::string(option_arg
));
1256 option_arg
.getAsInteger(0, m_line_num
);
1260 llvm_unreachable("Unimplemented option");
1266 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1271 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1272 return llvm::ArrayRef(g_breakpoint_clear_options
);
1275 // Instance variables to hold the values for command options.
1277 std::string m_filename
;
1278 uint32_t m_line_num
= 0;
1282 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1283 Target
&target
= GetSelectedOrDummyTarget();
1285 // The following are the various types of breakpoints that could be
1287 // 1). -f -l (clearing breakpoint by source location)
1289 BreakpointClearType break_type
= eClearTypeInvalid
;
1291 if (m_options
.m_line_num
!= 0)
1292 break_type
= eClearTypeFileAndLine
;
1294 std::unique_lock
<std::recursive_mutex
> lock
;
1295 target
.GetBreakpointList().GetListMutex(lock
);
1297 BreakpointList
&breakpoints
= target
.GetBreakpointList();
1298 size_t num_breakpoints
= breakpoints
.GetSize();
1300 // Early return if there's no breakpoint at all.
1301 if (num_breakpoints
== 0) {
1302 result
.AppendError("Breakpoint clear: No breakpoint cleared.");
1306 // Find matching breakpoints and delete them.
1308 // First create a copy of all the IDs.
1309 std::vector
<break_id_t
> BreakIDs
;
1310 for (size_t i
= 0; i
< num_breakpoints
; ++i
)
1311 BreakIDs
.push_back(breakpoints
.GetBreakpointAtIndex(i
)->GetID());
1313 int num_cleared
= 0;
1315 switch (break_type
) {
1316 case eClearTypeFileAndLine
: // Breakpoint by source position
1318 const ConstString
filename(m_options
.m_filename
.c_str());
1319 BreakpointLocationCollection loc_coll
;
1321 for (size_t i
= 0; i
< num_breakpoints
; ++i
) {
1322 Breakpoint
*bp
= breakpoints
.FindBreakpointByID(BreakIDs
[i
]).get();
1324 if (bp
->GetMatchingFileLine(filename
, m_options
.m_line_num
, loc_coll
)) {
1325 // If the collection size is 0, it's a full match and we can just
1326 // remove the breakpoint.
1327 if (loc_coll
.GetSize() == 0) {
1328 bp
->GetDescription(&ss
, lldb::eDescriptionLevelBrief
);
1330 target
.RemoveBreakpointByID(bp
->GetID());
1341 if (num_cleared
> 0) {
1342 Stream
&output_stream
= result
.GetOutputStream();
1343 output_stream
.Printf("%d breakpoints cleared:\n", num_cleared
);
1344 output_stream
<< ss
.GetString();
1345 output_stream
.EOL();
1346 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1348 result
.AppendError("Breakpoint clear: No breakpoint cleared.");
1353 CommandOptions m_options
;
1356 // CommandObjectBreakpointDelete
1357 #define LLDB_OPTIONS_breakpoint_delete
1358 #include "CommandOptions.inc"
1362 class CommandObjectBreakpointDelete
: public CommandObjectParsed
{
1364 CommandObjectBreakpointDelete(CommandInterpreter
&interpreter
)
1365 : CommandObjectParsed(interpreter
, "breakpoint delete",
1366 "Delete the specified breakpoint(s). If no "
1367 "breakpoints are specified, delete them all.",
1369 CommandArgumentEntry arg
;
1370 CommandObject::AddIDsArgumentData(arg
, eArgTypeBreakpointID
,
1371 eArgTypeBreakpointIDRange
);
1372 // Add the entry for the first argument for this command to the object's
1373 // arguments vector.
1374 m_arguments
.push_back(arg
);
1377 ~CommandObjectBreakpointDelete() override
= default;
1380 HandleArgumentCompletion(CompletionRequest
&request
,
1381 OptionElementVector
&opt_element_vector
) override
{
1382 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1383 GetCommandInterpreter(), lldb::eBreakpointCompletion
, request
, nullptr);
1386 Options
*GetOptions() override
{ return &m_options
; }
1388 class CommandOptions
: public Options
{
1390 CommandOptions() = default;
1392 ~CommandOptions() override
= default;
1394 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1395 ExecutionContext
*execution_context
) override
{
1397 const int short_option
= m_getopt_table
[option_idx
].val
;
1399 switch (short_option
) {
1409 m_delete_disabled
= true;
1413 llvm_unreachable("Unimplemented option");
1419 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1420 m_use_dummy
= false;
1422 m_delete_disabled
= false;
1425 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1426 return llvm::ArrayRef(g_breakpoint_delete_options
);
1429 // Instance variables to hold the values for command options.
1430 bool m_use_dummy
= false;
1431 bool m_force
= false;
1432 bool m_delete_disabled
= false;
1436 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1437 Target
&target
= GetSelectedOrDummyTarget(m_options
.m_use_dummy
);
1440 std::unique_lock
<std::recursive_mutex
> lock
;
1441 target
.GetBreakpointList().GetListMutex(lock
);
1443 BreakpointList
&breakpoints
= target
.GetBreakpointList();
1445 size_t num_breakpoints
= breakpoints
.GetSize();
1447 if (num_breakpoints
== 0) {
1448 result
.AppendError("No breakpoints exist to be deleted.");
1452 // Handle the delete all breakpoints case:
1453 if (command
.empty() && !m_options
.m_delete_disabled
) {
1454 if (!m_options
.m_force
&&
1455 !m_interpreter
.Confirm(
1456 "About to delete all breakpoints, do you want to do that?",
1458 result
.AppendMessage("Operation cancelled...");
1460 target
.RemoveAllowedBreakpoints();
1461 result
.AppendMessageWithFormat(
1462 "All breakpoints removed. (%" PRIu64
" breakpoint%s)\n",
1463 (uint64_t)num_breakpoints
, num_breakpoints
> 1 ? "s" : "");
1465 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1469 // Either we have some kind of breakpoint specification(s),
1470 // or we are handling "break disable --deleted". Gather the list
1471 // of breakpoints to delete here, the we'll delete them below.
1472 BreakpointIDList valid_bp_ids
;
1474 if (m_options
.m_delete_disabled
) {
1475 BreakpointIDList excluded_bp_ids
;
1477 if (!command
.empty()) {
1478 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1479 command
, &target
, result
, &excluded_bp_ids
,
1480 BreakpointName::Permissions::PermissionKinds::deletePerm
);
1481 if (!result
.Succeeded())
1485 for (auto breakpoint_sp
: breakpoints
.Breakpoints()) {
1486 if (!breakpoint_sp
->IsEnabled() && breakpoint_sp
->AllowDelete()) {
1487 BreakpointID
bp_id(breakpoint_sp
->GetID());
1489 if (!excluded_bp_ids
.FindBreakpointID(bp_id
, &pos
))
1490 valid_bp_ids
.AddBreakpointID(breakpoint_sp
->GetID());
1493 if (valid_bp_ids
.GetSize() == 0) {
1494 result
.AppendError("No disabled breakpoints.");
1498 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
1499 command
, &target
, result
, &valid_bp_ids
,
1500 BreakpointName::Permissions::PermissionKinds::deletePerm
);
1501 if (!result
.Succeeded())
1505 int delete_count
= 0;
1506 int disable_count
= 0;
1507 const size_t count
= valid_bp_ids
.GetSize();
1508 for (size_t i
= 0; i
< count
; ++i
) {
1509 BreakpointID cur_bp_id
= valid_bp_ids
.GetBreakpointIDAtIndex(i
);
1511 if (cur_bp_id
.GetBreakpointID() != LLDB_INVALID_BREAK_ID
) {
1512 if (cur_bp_id
.GetLocationID() != LLDB_INVALID_BREAK_ID
) {
1513 Breakpoint
*breakpoint
=
1514 target
.GetBreakpointByID(cur_bp_id
.GetBreakpointID()).get();
1515 BreakpointLocation
*location
=
1516 breakpoint
->FindLocationByID(cur_bp_id
.GetLocationID()).get();
1517 // It makes no sense to try to delete individual locations, so we
1518 // disable them instead.
1520 location
->SetEnabled(false);
1524 target
.RemoveBreakpointByID(cur_bp_id
.GetBreakpointID());
1529 result
.AppendMessageWithFormat(
1530 "%d breakpoints deleted; %d breakpoint locations disabled.\n",
1531 delete_count
, disable_count
);
1532 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1536 CommandOptions m_options
;
1539 // CommandObjectBreakpointName
1540 #define LLDB_OPTIONS_breakpoint_name
1541 #include "CommandOptions.inc"
1543 class BreakpointNameOptionGroup
: public OptionGroup
{
1545 BreakpointNameOptionGroup()
1546 : m_breakpoint(LLDB_INVALID_BREAK_ID
), m_use_dummy(false) {}
1548 ~BreakpointNameOptionGroup() override
= default;
1550 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1551 return llvm::ArrayRef(g_breakpoint_name_options
);
1554 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1555 ExecutionContext
*execution_context
) override
{
1557 const int short_option
= g_breakpoint_name_options
[option_idx
].short_option
;
1559 switch (short_option
) {
1561 if (BreakpointID::StringIsBreakpointName(option_arg
, error
) &&
1563 m_name
.SetValueFromString(option_arg
);
1566 if (m_breakpoint
.SetValueFromString(option_arg
).Fail())
1567 error
.SetErrorStringWithFormat(
1568 "unrecognized value \"%s\" for breakpoint",
1569 option_arg
.str().c_str());
1572 if (m_use_dummy
.SetValueFromString(option_arg
).Fail())
1573 error
.SetErrorStringWithFormat(
1574 "unrecognized value \"%s\" for use-dummy",
1575 option_arg
.str().c_str());
1578 m_help_string
.SetValueFromString(option_arg
);
1582 llvm_unreachable("Unimplemented option");
1587 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1589 m_breakpoint
.Clear();
1590 m_use_dummy
.Clear();
1591 m_use_dummy
.SetDefaultValue(false);
1592 m_help_string
.Clear();
1595 OptionValueString m_name
;
1596 OptionValueUInt64 m_breakpoint
;
1597 OptionValueBoolean m_use_dummy
;
1598 OptionValueString m_help_string
;
1601 #define LLDB_OPTIONS_breakpoint_access
1602 #include "CommandOptions.inc"
1604 class BreakpointAccessOptionGroup
: public OptionGroup
{
1606 BreakpointAccessOptionGroup() = default;
1608 ~BreakpointAccessOptionGroup() override
= default;
1610 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1611 return llvm::ArrayRef(g_breakpoint_access_options
);
1613 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1614 ExecutionContext
*execution_context
) override
{
1616 const int short_option
=
1617 g_breakpoint_access_options
[option_idx
].short_option
;
1619 switch (short_option
) {
1621 bool value
, success
;
1622 value
= OptionArgParser::ToBoolean(option_arg
, false, &success
);
1624 m_permissions
.SetAllowList(value
);
1626 error
.SetErrorStringWithFormat(
1627 "invalid boolean value '%s' passed for -L option",
1628 option_arg
.str().c_str());
1631 bool value
, success
;
1632 value
= OptionArgParser::ToBoolean(option_arg
, false, &success
);
1634 m_permissions
.SetAllowDisable(value
);
1636 error
.SetErrorStringWithFormat(
1637 "invalid boolean value '%s' passed for -L option",
1638 option_arg
.str().c_str());
1641 bool value
, success
;
1642 value
= OptionArgParser::ToBoolean(option_arg
, false, &success
);
1644 m_permissions
.SetAllowDelete(value
);
1646 error
.SetErrorStringWithFormat(
1647 "invalid boolean value '%s' passed for -L option",
1648 option_arg
.str().c_str());
1651 llvm_unreachable("Unimplemented option");
1657 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{}
1659 const BreakpointName::Permissions
&GetPermissions() const {
1660 return m_permissions
;
1662 BreakpointName::Permissions m_permissions
;
1665 class CommandObjectBreakpointNameConfigure
: public CommandObjectParsed
{
1667 CommandObjectBreakpointNameConfigure(CommandInterpreter
&interpreter
)
1668 : CommandObjectParsed(
1669 interpreter
, "configure",
1670 "Configure the options for the breakpoint"
1672 "If you provide a breakpoint id, the options will be copied from "
1673 "the breakpoint, otherwise only the options specified will be set "
1675 "breakpoint name configure <command-options> "
1676 "<breakpoint-name-list>") {
1677 // Create the first variant for the first (and only) argument for this
1679 CommandArgumentEntry arg1
;
1680 CommandArgumentData id_arg
;
1681 id_arg
.arg_type
= eArgTypeBreakpointName
;
1682 id_arg
.arg_repetition
= eArgRepeatOptional
;
1683 arg1
.push_back(id_arg
);
1684 m_arguments
.push_back(arg1
);
1686 m_option_group
.Append(&m_bp_opts
, LLDB_OPT_SET_ALL
, LLDB_OPT_SET_1
);
1687 m_option_group
.Append(&m_access_options
, LLDB_OPT_SET_ALL
,
1689 m_option_group
.Append(&m_bp_id
, LLDB_OPT_SET_2
| LLDB_OPT_SET_4
,
1691 m_option_group
.Finalize();
1694 ~CommandObjectBreakpointNameConfigure() override
= default;
1696 Options
*GetOptions() override
{ return &m_option_group
; }
1699 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1701 const size_t argc
= command
.GetArgumentCount();
1703 result
.AppendError("No names provided.");
1707 Target
&target
= GetSelectedOrDummyTarget(false);
1709 std::unique_lock
<std::recursive_mutex
> lock
;
1710 target
.GetBreakpointList().GetListMutex(lock
);
1712 // Make a pass through first to see that all the names are legal.
1713 for (auto &entry
: command
.entries()) {
1715 if (!BreakpointID::StringIsBreakpointName(entry
.ref(), error
)) {
1716 result
.AppendErrorWithFormat("Invalid breakpoint name: %s - %s",
1717 entry
.c_str(), error
.AsCString());
1721 // Now configure them, we already pre-checked the names so we don't need to
1724 if (m_bp_id
.m_breakpoint
.OptionWasSet()) {
1725 lldb::break_id_t bp_id
=
1726 m_bp_id
.m_breakpoint
.GetValueAs
<uint64_t>().value_or(0);
1727 bp_sp
= target
.GetBreakpointByID(bp_id
);
1729 result
.AppendErrorWithFormatv("Could not find specified breakpoint {0}",
1736 for (auto &entry
: command
.entries()) {
1737 ConstString
name(entry
.c_str());
1738 BreakpointName
*bp_name
= target
.FindBreakpointName(name
, true, error
);
1741 if (m_bp_id
.m_help_string
.OptionWasSet())
1742 bp_name
->SetHelp(m_bp_id
.m_help_string
.GetValueAs
<llvm::StringRef
>()
1748 target
.ConfigureBreakpointName(*bp_name
, bp_sp
->GetOptions(),
1749 m_access_options
.GetPermissions());
1751 target
.ConfigureBreakpointName(*bp_name
,
1752 m_bp_opts
.GetBreakpointOptions(),
1753 m_access_options
.GetPermissions());
1758 BreakpointNameOptionGroup m_bp_id
; // Only using the id part of this.
1759 BreakpointOptionGroup m_bp_opts
;
1760 BreakpointAccessOptionGroup m_access_options
;
1761 OptionGroupOptions m_option_group
;
1764 class CommandObjectBreakpointNameAdd
: public CommandObjectParsed
{
1766 CommandObjectBreakpointNameAdd(CommandInterpreter
&interpreter
)
1767 : CommandObjectParsed(
1768 interpreter
, "add", "Add a name to the breakpoints provided.",
1769 "breakpoint name add <command-options> <breakpoint-id-list>") {
1770 // Create the first variant for the first (and only) argument for this
1772 CommandArgumentEntry arg1
;
1773 CommandArgumentData id_arg
;
1774 id_arg
.arg_type
= eArgTypeBreakpointID
;
1775 id_arg
.arg_repetition
= eArgRepeatOptional
;
1776 arg1
.push_back(id_arg
);
1777 m_arguments
.push_back(arg1
);
1779 m_option_group
.Append(&m_name_options
, LLDB_OPT_SET_1
, LLDB_OPT_SET_ALL
);
1780 m_option_group
.Finalize();
1783 ~CommandObjectBreakpointNameAdd() override
= default;
1786 HandleArgumentCompletion(CompletionRequest
&request
,
1787 OptionElementVector
&opt_element_vector
) override
{
1788 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1789 GetCommandInterpreter(), lldb::eBreakpointCompletion
, request
, nullptr);
1792 Options
*GetOptions() override
{ return &m_option_group
; }
1795 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1796 if (!m_name_options
.m_name
.OptionWasSet()) {
1797 result
.AppendError("No name option provided.");
1802 GetSelectedOrDummyTarget(m_name_options
.m_use_dummy
.GetCurrentValue());
1804 std::unique_lock
<std::recursive_mutex
> lock
;
1805 target
.GetBreakpointList().GetListMutex(lock
);
1807 const BreakpointList
&breakpoints
= target
.GetBreakpointList();
1809 size_t num_breakpoints
= breakpoints
.GetSize();
1810 if (num_breakpoints
== 0) {
1811 result
.AppendError("No breakpoints, cannot add names.");
1815 // Particular breakpoint selected; disable that breakpoint.
1816 BreakpointIDList valid_bp_ids
;
1817 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1818 command
, &target
, result
, &valid_bp_ids
,
1819 BreakpointName::Permissions::PermissionKinds::listPerm
);
1821 if (result
.Succeeded()) {
1822 if (valid_bp_ids
.GetSize() == 0) {
1823 result
.AppendError("No breakpoints specified, cannot add names.");
1826 size_t num_valid_ids
= valid_bp_ids
.GetSize();
1827 const char *bp_name
= m_name_options
.m_name
.GetCurrentValue();
1828 Status error
; // This error reports illegal names, but we've already
1829 // checked that, so we don't need to check it again here.
1830 for (size_t index
= 0; index
< num_valid_ids
; index
++) {
1831 lldb::break_id_t bp_id
=
1832 valid_bp_ids
.GetBreakpointIDAtIndex(index
).GetBreakpointID();
1833 BreakpointSP bp_sp
= breakpoints
.FindBreakpointByID(bp_id
);
1834 target
.AddNameToBreakpoint(bp_sp
, bp_name
, error
);
1840 BreakpointNameOptionGroup m_name_options
;
1841 OptionGroupOptions m_option_group
;
1844 class CommandObjectBreakpointNameDelete
: public CommandObjectParsed
{
1846 CommandObjectBreakpointNameDelete(CommandInterpreter
&interpreter
)
1847 : CommandObjectParsed(
1848 interpreter
, "delete",
1849 "Delete a name from the breakpoints provided.",
1850 "breakpoint name delete <command-options> <breakpoint-id-list>") {
1851 // Create the first variant for the first (and only) argument for this
1853 CommandArgumentEntry arg1
;
1854 CommandArgumentData id_arg
;
1855 id_arg
.arg_type
= eArgTypeBreakpointID
;
1856 id_arg
.arg_repetition
= eArgRepeatOptional
;
1857 arg1
.push_back(id_arg
);
1858 m_arguments
.push_back(arg1
);
1860 m_option_group
.Append(&m_name_options
, LLDB_OPT_SET_1
, LLDB_OPT_SET_ALL
);
1861 m_option_group
.Finalize();
1864 ~CommandObjectBreakpointNameDelete() override
= default;
1867 HandleArgumentCompletion(CompletionRequest
&request
,
1868 OptionElementVector
&opt_element_vector
) override
{
1869 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1870 GetCommandInterpreter(), lldb::eBreakpointCompletion
, request
, nullptr);
1873 Options
*GetOptions() override
{ return &m_option_group
; }
1876 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1877 if (!m_name_options
.m_name
.OptionWasSet()) {
1878 result
.AppendError("No name option provided.");
1883 GetSelectedOrDummyTarget(m_name_options
.m_use_dummy
.GetCurrentValue());
1885 std::unique_lock
<std::recursive_mutex
> lock
;
1886 target
.GetBreakpointList().GetListMutex(lock
);
1888 const BreakpointList
&breakpoints
= target
.GetBreakpointList();
1890 size_t num_breakpoints
= breakpoints
.GetSize();
1891 if (num_breakpoints
== 0) {
1892 result
.AppendError("No breakpoints, cannot delete names.");
1896 // Particular breakpoint selected; disable that breakpoint.
1897 BreakpointIDList valid_bp_ids
;
1898 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
1899 command
, &target
, result
, &valid_bp_ids
,
1900 BreakpointName::Permissions::PermissionKinds::deletePerm
);
1902 if (result
.Succeeded()) {
1903 if (valid_bp_ids
.GetSize() == 0) {
1904 result
.AppendError("No breakpoints specified, cannot delete names.");
1907 ConstString
bp_name(m_name_options
.m_name
.GetCurrentValue());
1908 size_t num_valid_ids
= valid_bp_ids
.GetSize();
1909 for (size_t index
= 0; index
< num_valid_ids
; index
++) {
1910 lldb::break_id_t bp_id
=
1911 valid_bp_ids
.GetBreakpointIDAtIndex(index
).GetBreakpointID();
1912 BreakpointSP bp_sp
= breakpoints
.FindBreakpointByID(bp_id
);
1913 target
.RemoveNameFromBreakpoint(bp_sp
, bp_name
);
1919 BreakpointNameOptionGroup m_name_options
;
1920 OptionGroupOptions m_option_group
;
1923 class CommandObjectBreakpointNameList
: public CommandObjectParsed
{
1925 CommandObjectBreakpointNameList(CommandInterpreter
&interpreter
)
1926 : CommandObjectParsed(interpreter
, "list",
1927 "List either the names for a breakpoint or info "
1928 "about a given name. With no arguments, lists all "
1930 "breakpoint name list <command-options>") {
1931 m_option_group
.Append(&m_name_options
, LLDB_OPT_SET_3
, LLDB_OPT_SET_ALL
);
1932 m_option_group
.Finalize();
1935 ~CommandObjectBreakpointNameList() override
= default;
1937 Options
*GetOptions() override
{ return &m_option_group
; }
1940 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1942 GetSelectedOrDummyTarget(m_name_options
.m_use_dummy
.GetCurrentValue());
1944 std::vector
<std::string
> name_list
;
1945 if (command
.empty()) {
1946 target
.GetBreakpointNames(name_list
);
1948 for (const Args::ArgEntry
&arg
: command
) {
1949 name_list
.push_back(arg
.c_str());
1953 if (name_list
.empty()) {
1954 result
.AppendMessage("No breakpoint names found.");
1956 for (const std::string
&name_str
: name_list
) {
1957 const char *name
= name_str
.c_str();
1958 // First print out the options for the name:
1960 BreakpointName
*bp_name
=
1961 target
.FindBreakpointName(ConstString(name
), false, error
);
1964 result
.AppendMessageWithFormat("Name: %s\n", name
);
1965 if (bp_name
->GetDescription(&s
, eDescriptionLevelFull
)) {
1966 result
.AppendMessage(s
.GetString());
1969 std::unique_lock
<std::recursive_mutex
> lock
;
1970 target
.GetBreakpointList().GetListMutex(lock
);
1972 BreakpointList
&breakpoints
= target
.GetBreakpointList();
1973 bool any_set
= false;
1974 for (BreakpointSP bp_sp
: breakpoints
.Breakpoints()) {
1975 if (bp_sp
->MatchesName(name
)) {
1978 bp_sp
->GetDescription(&s
, eDescriptionLevelBrief
);
1980 result
.AppendMessage(s
.GetString());
1984 result
.AppendMessage("No breakpoints using this name.");
1986 result
.AppendMessageWithFormat("Name: %s not found.\n", name
);
1993 BreakpointNameOptionGroup m_name_options
;
1994 OptionGroupOptions m_option_group
;
1997 // CommandObjectBreakpointName
1998 class CommandObjectBreakpointName
: public CommandObjectMultiword
{
2000 CommandObjectBreakpointName(CommandInterpreter
&interpreter
)
2001 : CommandObjectMultiword(
2002 interpreter
, "name", "Commands to manage breakpoint names") {
2007 Breakpoint names provide a general tagging mechanism for breakpoints. Each
2008 breakpoint name can be added to any number of breakpoints, and each breakpoint
2009 can have any number of breakpoint names attached to it. For instance:
2011 (lldb) break name add -N MyName 1-10
2013 adds the name MyName to breakpoints 1-10, and:
2015 (lldb) break set -n myFunc -N Name1 -N Name2
2017 adds two names to the breakpoint set at myFunc.
2019 They have a number of interrelated uses:
2021 1) They provide a stable way to refer to a breakpoint (e.g. in another
2022 breakpoint's action). Using the breakpoint ID for this purpose is fragile, since
2023 it depends on the order of breakpoint creation. Giving a name to the breakpoint
2024 you want to act on, and then referring to it by name, is more robust:
2026 (lldb) break set -n myFunc -N BKPT1
2027 (lldb) break set -n myOtherFunc -C "break disable BKPT1
"
2029 2) This is actually just a specific use of a more general feature of breakpoint
2030 names. The <breakpt-id-list> argument type used to specify one or more
2031 breakpoints in most of the commands that deal with breakpoints also accepts
2032 breakpoint names. That allows you to refer to one breakpoint in a stable
2033 manner, but also makes them a convenient grouping mechanism, allowing you to
2034 easily act on a group of breakpoints by using their name, for instance disabling
2035 them all in one action:
2037 (lldb) break set -n myFunc -N Group1
2038 (lldb) break set -n myOtherFunc -N Group1
2039 (lldb) break disable Group1
2041 3) But breakpoint names are also entities in their own right, and can be
2042 configured with all the modifiable attributes of a breakpoint. Then when you
2043 add a breakpoint name to a breakpoint, the breakpoint will be configured to
2044 match the state of the breakpoint name. The link between the name and the
2045 breakpoints sharing it remains live, so if you change the configuration on the
2046 name, it will also change the configurations on the breakpoints:
2048 (lldb) break name configure -i 10 IgnoreSome
2049 (lldb) break set -n myFunc -N IgnoreSome
2050 (lldb) break list IgnoreSome
2051 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 10 enabled
2054 (lldb) break name configure -i 5 IgnoreSome
2055 (lldb) break list IgnoreSome
2056 2: name = 'myFunc', locations = 0 (pending) Options: ignore: 5 enabled
2060 Options that are not configured on a breakpoint name don't affect the value of
2061 those options on the breakpoints they are added to. So for instance, if Name1
2062 has the -i option configured and Name2 the -c option, adding both names to a
2063 breakpoint will set the -i option from Name1 and the -c option from Name2, and
2064 the other options will be unaltered.
2066 If you add multiple names to a breakpoint which have configured values for
2067 the same option, the last name added's value wins.
2069 The "liveness
" of these settings is one way, from name to breakpoint.
2070 If you use "break modify
" to change an option that is also configured on a name
2071 which that breakpoint has, the "break modify
" command will override the setting
2072 for that breakpoint, but won't change the value configured in the name or on the
2073 other breakpoints sharing that name.
2075 4) Breakpoint names are also a convenient way to copy option sets from one
2076 breakpoint to another. Using the -B option to "breakpoint name configure
" makes
2077 a name configured with all the options of the original breakpoint. Then
2078 adding that name to another breakpoint copies over all the values from the
2079 original breakpoint to the new one.
2081 5) You can also use breakpoint names to hide breakpoints from the breakpoint
2082 operations that act on all breakpoints: "break delete", "break disable
" and
2083 "break list
". You do that by specifying a "false" value for the
2084 --allow-{list,delete,disable} options to "breakpoint name configure
" and then
2085 adding that name to a breakpoint.
2087 This won't keep the breakpoint from being deleted or disabled if you refer to it
2088 specifically by ID. The point of the feature is to make sure users don't
2089 inadvertently delete or disable useful breakpoints (e.g. ones an IDE is using
2090 for its own purposes) as part of a "delete all
" or "disable all
" operation. The
2091 list hiding is because it's confusing for people to see breakpoints they
2095 CommandObjectSP
add_command_object(
2096 new CommandObjectBreakpointNameAdd(interpreter
));
2097 CommandObjectSP
delete_command_object(
2098 new CommandObjectBreakpointNameDelete(interpreter
));
2099 CommandObjectSP
list_command_object(
2100 new CommandObjectBreakpointNameList(interpreter
));
2101 CommandObjectSP
configure_command_object(
2102 new CommandObjectBreakpointNameConfigure(interpreter
));
2104 LoadSubCommand("add", add_command_object
);
2105 LoadSubCommand("delete", delete_command_object
);
2106 LoadSubCommand("list", list_command_object
);
2107 LoadSubCommand("configure", configure_command_object
);
2110 ~CommandObjectBreakpointName() override
= default;
2113 // CommandObjectBreakpointRead
2114 #pragma mark Read::CommandOptions
2115 #define LLDB_OPTIONS_breakpoint_read
2116 #include "CommandOptions.inc"
2120 class CommandObjectBreakpointRead
: public CommandObjectParsed
{
2122 CommandObjectBreakpointRead(CommandInterpreter
&interpreter
)
2123 : CommandObjectParsed(interpreter
, "breakpoint read",
2124 "Read and set the breakpoints previously saved to "
2125 "a file with \"breakpoint write\". ",
2128 ~CommandObjectBreakpointRead() override
= default;
2130 Options
*GetOptions() override
{ return &m_options
; }
2132 class CommandOptions
: public Options
{
2134 CommandOptions() = default;
2136 ~CommandOptions() override
= default;
2138 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2139 ExecutionContext
*execution_context
) override
{
2141 const int short_option
= m_getopt_table
[option_idx
].val
;
2143 switch (short_option
) {
2145 m_filename
.assign(std::string(option_arg
));
2149 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg
),
2151 error
.SetErrorStringWithFormat("Invalid breakpoint name: %s",
2152 name_error
.AsCString());
2154 m_names
.push_back(std::string(option_arg
));
2158 llvm_unreachable("Unimplemented option");
2164 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2169 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2170 return llvm::ArrayRef(g_breakpoint_read_options
);
2173 void HandleOptionArgumentCompletion(
2174 CompletionRequest
&request
, OptionElementVector
&opt_element_vector
,
2175 int opt_element_index
, CommandInterpreter
&interpreter
) override
{
2176 int opt_arg_pos
= opt_element_vector
[opt_element_index
].opt_arg_pos
;
2177 int opt_defs_index
= opt_element_vector
[opt_element_index
].opt_defs_index
;
2179 switch (GetDefinitions()[opt_defs_index
].short_option
) {
2181 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2182 interpreter
, lldb::eDiskFileCompletion
, request
, nullptr);
2186 std::optional
<FileSpec
> file_spec
;
2187 const llvm::StringRef
dash_f("-f");
2188 for (int arg_idx
= 0; arg_idx
< opt_arg_pos
; arg_idx
++) {
2189 if (dash_f
== request
.GetParsedLine().GetArgumentAtIndex(arg_idx
)) {
2191 request
.GetParsedLine().GetArgumentAtIndex(arg_idx
+ 1));
2198 FileSystem::Instance().Resolve(*file_spec
);
2200 StructuredData::ObjectSP input_data_sp
=
2201 StructuredData::ParseJSONFromFile(*file_spec
, error
);
2202 if (!error
.Success())
2205 StructuredData::Array
*bkpt_array
= input_data_sp
->GetAsArray();
2209 const size_t num_bkpts
= bkpt_array
->GetSize();
2210 for (size_t i
= 0; i
< num_bkpts
; i
++) {
2211 StructuredData::ObjectSP bkpt_object_sp
=
2212 bkpt_array
->GetItemAtIndex(i
);
2213 if (!bkpt_object_sp
)
2216 StructuredData::Dictionary
*bkpt_dict
=
2217 bkpt_object_sp
->GetAsDictionary();
2221 StructuredData::ObjectSP bkpt_data_sp
=
2222 bkpt_dict
->GetValueForKey(Breakpoint::GetSerializationKey());
2226 bkpt_dict
= bkpt_data_sp
->GetAsDictionary();
2230 StructuredData::Array
*names_array
;
2232 if (!bkpt_dict
->GetValueForKeyAsArray("Names", names_array
))
2235 size_t num_names
= names_array
->GetSize();
2237 for (size_t i
= 0; i
< num_names
; i
++) {
2238 llvm::StringRef name
;
2239 if (names_array
->GetItemAtIndexAsString(i
, name
))
2240 request
.TryCompleteCurrentArg(name
);
2246 std::string m_filename
;
2247 std::vector
<std::string
> m_names
;
2251 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2252 Target
&target
= GetSelectedOrDummyTarget();
2254 std::unique_lock
<std::recursive_mutex
> lock
;
2255 target
.GetBreakpointList().GetListMutex(lock
);
2257 FileSpec
input_spec(m_options
.m_filename
);
2258 FileSystem::Instance().Resolve(input_spec
);
2259 BreakpointIDList new_bps
;
2260 Status error
= target
.CreateBreakpointsFromFile(input_spec
,
2261 m_options
.m_names
, new_bps
);
2263 if (!error
.Success()) {
2264 result
.AppendError(error
.AsCString());
2268 Stream
&output_stream
= result
.GetOutputStream();
2270 size_t num_breakpoints
= new_bps
.GetSize();
2271 if (num_breakpoints
== 0) {
2272 result
.AppendMessage("No breakpoints added.");
2274 // No breakpoint selected; show info about all currently set breakpoints.
2275 result
.AppendMessage("New breakpoints:");
2276 for (size_t i
= 0; i
< num_breakpoints
; ++i
) {
2277 BreakpointID bp_id
= new_bps
.GetBreakpointIDAtIndex(i
);
2278 Breakpoint
*bp
= target
.GetBreakpointList()
2279 .FindBreakpointByID(bp_id
.GetBreakpointID())
2282 bp
->GetDescription(&output_stream
, lldb::eDescriptionLevelInitial
,
2289 CommandOptions m_options
;
2292 // CommandObjectBreakpointWrite
2293 #pragma mark Write::CommandOptions
2294 #define LLDB_OPTIONS_breakpoint_write
2295 #include "CommandOptions.inc"
2298 class CommandObjectBreakpointWrite
: public CommandObjectParsed
{
2300 CommandObjectBreakpointWrite(CommandInterpreter
&interpreter
)
2301 : CommandObjectParsed(interpreter
, "breakpoint write",
2302 "Write the breakpoints listed to a file that can "
2303 "be read in with \"breakpoint read\". "
2304 "If given no arguments, writes all breakpoints.",
2306 CommandArgumentEntry arg
;
2307 CommandObject::AddIDsArgumentData(arg
, eArgTypeBreakpointID
,
2308 eArgTypeBreakpointIDRange
);
2309 // Add the entry for the first argument for this command to the object's
2310 // arguments vector.
2311 m_arguments
.push_back(arg
);
2314 ~CommandObjectBreakpointWrite() override
= default;
2317 HandleArgumentCompletion(CompletionRequest
&request
,
2318 OptionElementVector
&opt_element_vector
) override
{
2319 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
2320 GetCommandInterpreter(), lldb::eBreakpointCompletion
, request
, nullptr);
2323 Options
*GetOptions() override
{ return &m_options
; }
2325 class CommandOptions
: public Options
{
2327 CommandOptions() = default;
2329 ~CommandOptions() override
= default;
2331 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
2332 ExecutionContext
*execution_context
) override
{
2334 const int short_option
= m_getopt_table
[option_idx
].val
;
2336 switch (short_option
) {
2338 m_filename
.assign(std::string(option_arg
));
2344 llvm_unreachable("Unimplemented option");
2350 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
2355 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
2356 return llvm::ArrayRef(g_breakpoint_write_options
);
2359 // Instance variables to hold the values for command options.
2361 std::string m_filename
;
2362 bool m_append
= false;
2366 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
2367 Target
&target
= GetSelectedOrDummyTarget();
2369 std::unique_lock
<std::recursive_mutex
> lock
;
2370 target
.GetBreakpointList().GetListMutex(lock
);
2372 BreakpointIDList valid_bp_ids
;
2373 if (!command
.empty()) {
2374 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs(
2375 command
, &target
, result
, &valid_bp_ids
,
2376 BreakpointName::Permissions::PermissionKinds::listPerm
);
2378 if (!result
.Succeeded()) {
2379 result
.SetStatus(eReturnStatusFailed
);
2383 FileSpec
file_spec(m_options
.m_filename
);
2384 FileSystem::Instance().Resolve(file_spec
);
2385 Status error
= target
.SerializeBreakpointsToFile(file_spec
, valid_bp_ids
,
2386 m_options
.m_append
);
2387 if (!error
.Success()) {
2388 result
.AppendErrorWithFormat("error serializing breakpoints: %s.",
2394 CommandOptions m_options
;
2397 // CommandObjectMultiwordBreakpoint
2398 #pragma mark MultiwordBreakpoint
2400 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(
2401 CommandInterpreter
&interpreter
)
2402 : CommandObjectMultiword(
2403 interpreter
, "breakpoint",
2404 "Commands for operating on breakpoints (see 'help b' for shorthand.)",
2405 "breakpoint <subcommand> [<command-options>]") {
2406 CommandObjectSP
list_command_object(
2407 new CommandObjectBreakpointList(interpreter
));
2408 CommandObjectSP
enable_command_object(
2409 new CommandObjectBreakpointEnable(interpreter
));
2410 CommandObjectSP
disable_command_object(
2411 new CommandObjectBreakpointDisable(interpreter
));
2412 CommandObjectSP
clear_command_object(
2413 new CommandObjectBreakpointClear(interpreter
));
2414 CommandObjectSP
delete_command_object(
2415 new CommandObjectBreakpointDelete(interpreter
));
2416 CommandObjectSP
set_command_object(
2417 new CommandObjectBreakpointSet(interpreter
));
2418 CommandObjectSP
command_command_object(
2419 new CommandObjectBreakpointCommand(interpreter
));
2420 CommandObjectSP
modify_command_object(
2421 new CommandObjectBreakpointModify(interpreter
));
2422 CommandObjectSP
name_command_object(
2423 new CommandObjectBreakpointName(interpreter
));
2424 CommandObjectSP
write_command_object(
2425 new CommandObjectBreakpointWrite(interpreter
));
2426 CommandObjectSP
read_command_object(
2427 new CommandObjectBreakpointRead(interpreter
));
2429 list_command_object
->SetCommandName("breakpoint list");
2430 enable_command_object
->SetCommandName("breakpoint enable");
2431 disable_command_object
->SetCommandName("breakpoint disable");
2432 clear_command_object
->SetCommandName("breakpoint clear");
2433 delete_command_object
->SetCommandName("breakpoint delete");
2434 set_command_object
->SetCommandName("breakpoint set");
2435 command_command_object
->SetCommandName("breakpoint command");
2436 modify_command_object
->SetCommandName("breakpoint modify");
2437 name_command_object
->SetCommandName("breakpoint name");
2438 write_command_object
->SetCommandName("breakpoint write");
2439 read_command_object
->SetCommandName("breakpoint read");
2441 LoadSubCommand("list", list_command_object
);
2442 LoadSubCommand("enable", enable_command_object
);
2443 LoadSubCommand("disable", disable_command_object
);
2444 LoadSubCommand("clear", clear_command_object
);
2445 LoadSubCommand("delete", delete_command_object
);
2446 LoadSubCommand("set", set_command_object
);
2447 LoadSubCommand("command", command_command_object
);
2448 LoadSubCommand("modify", modify_command_object
);
2449 LoadSubCommand("name", name_command_object
);
2450 LoadSubCommand("write", write_command_object
);
2451 LoadSubCommand("read", read_command_object
);
2454 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default;
2456 void CommandObjectMultiwordBreakpoint::VerifyIDs(
2457 Args
&args
, Target
*target
, bool allow_locations
,
2458 CommandReturnObject
&result
, BreakpointIDList
*valid_ids
,
2459 BreakpointName::Permissions ::PermissionKinds purpose
) {
2460 // args can be strings representing 1). integers (for breakpoint ids)
2461 // 2). the full breakpoint & location
2462 // canonical representation
2463 // 3). the word "to" or a hyphen,
2464 // representing a range (in which case there
2465 // had *better* be an entry both before &
2466 // after of one of the first two types.
2467 // 4). A breakpoint name
2468 // If args is empty, we will use the last created breakpoint (if there is
2474 if (target
->GetLastCreatedBreakpoint()) {
2475 valid_ids
->AddBreakpointID(BreakpointID(
2476 target
->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID
));
2477 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
2480 "No breakpoint specified and no last created breakpoint.");
2485 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff
2486 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint
2487 // id range strings over; instead generate a list of strings for all the
2488 // breakpoint ids in the range, and shove all of those breakpoint id strings
2491 BreakpointIDList::FindAndReplaceIDRanges(args
, target
, allow_locations
,
2492 purpose
, result
, temp_args
);
2494 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual
2495 // BreakpointIDList:
2497 valid_ids
->InsertStringArray(temp_args
.GetArgumentArrayRef(), result
);
2499 // At this point, all of the breakpoint ids that the user passed in have
2500 // been converted to breakpoint IDs and put into valid_ids.
2502 if (result
.Succeeded()) {
2503 // Now that we've converted everything from args into a list of breakpoint
2504 // ids, go through our tentative list of breakpoint id's and verify that
2505 // they correspond to valid/currently set breakpoints.
2507 const size_t count
= valid_ids
->GetSize();
2508 for (size_t i
= 0; i
< count
; ++i
) {
2509 BreakpointID cur_bp_id
= valid_ids
->GetBreakpointIDAtIndex(i
);
2510 Breakpoint
*breakpoint
=
2511 target
->GetBreakpointByID(cur_bp_id
.GetBreakpointID()).get();
2512 if (breakpoint
!= nullptr) {
2513 const size_t num_locations
= breakpoint
->GetNumLocations();
2514 if (static_cast<size_t>(cur_bp_id
.GetLocationID()) > num_locations
) {
2515 StreamString id_str
;
2516 BreakpointID::GetCanonicalReference(
2517 &id_str
, cur_bp_id
.GetBreakpointID(), cur_bp_id
.GetLocationID());
2518 i
= valid_ids
->GetSize() + 1;
2519 result
.AppendErrorWithFormat(
2520 "'%s' is not a currently valid breakpoint/location id.\n",
2524 i
= valid_ids
->GetSize() + 1;
2525 result
.AppendErrorWithFormat(
2526 "'%d' is not a currently valid breakpoint ID.\n",
2527 cur_bp_id
.GetBreakpointID());