1 //===-- CommandObjectWatchpoint.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 "CommandObjectWatchpoint.h"
10 #include "CommandObjectWatchpointCommand.h"
15 #include "llvm/ADT/StringRef.h"
17 #include "lldb/Breakpoint/Watchpoint.h"
18 #include "lldb/Breakpoint/WatchpointList.h"
19 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Host/OptionParser.h"
21 #include "lldb/Interpreter/CommandInterpreter.h"
22 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
23 #include "lldb/Interpreter/CommandReturnObject.h"
24 #include "lldb/Symbol/Function.h"
25 #include "lldb/Symbol/Variable.h"
26 #include "lldb/Symbol/VariableList.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Utility/StreamString.h"
32 using namespace lldb_private
;
34 static void AddWatchpointDescription(Stream
&s
, Watchpoint
&wp
,
35 lldb::DescriptionLevel level
) {
37 wp
.GetDescription(&s
, level
);
42 static bool CheckTargetForWatchpointOperations(Target
*target
,
43 CommandReturnObject
&result
) {
44 bool process_is_valid
=
45 target
->GetProcessSP() && target
->GetProcessSP()->IsAlive();
46 if (!process_is_valid
) {
47 result
.AppendError("There's no process or it is not alive.");
50 // Target passes our checks, return true.
54 // Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
55 static const char *RSA
[4] = {"-", "to", "To", "TO"};
57 // Return the index to RSA if found; otherwise -1 is returned.
58 static int32_t WithRSAIndex(llvm::StringRef Arg
) {
61 for (i
= 0; i
< 4; ++i
)
62 if (Arg
.contains(RSA
[i
]))
67 // Return true if wp_ids is successfully populated with the watch ids. False
69 bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
70 Target
*target
, Args
&args
, std::vector
<uint32_t> &wp_ids
) {
71 // Pre-condition: args.GetArgumentCount() > 0.
72 if (args
.GetArgumentCount() == 0) {
73 if (target
== nullptr)
75 WatchpointSP watch_sp
= target
->GetLastCreatedWatchpoint();
77 wp_ids
.push_back(watch_sp
->GetID());
83 llvm::StringRef
Minus("-");
84 std::vector
<llvm::StringRef
> StrRefArgs
;
85 llvm::StringRef first
;
86 llvm::StringRef second
;
89 // Go through the arguments and make a canonical form of arg list containing
90 // only numbers with possible "-" in between.
91 for (auto &entry
: args
.entries()) {
92 if ((idx
= WithRSAIndex(entry
.ref())) == -1) {
93 StrRefArgs
.push_back(entry
.ref());
96 // The Arg contains the range specifier, split it, then.
97 std::tie(first
, second
) = entry
.ref().split(RSA
[idx
]);
99 StrRefArgs
.push_back(first
);
100 StrRefArgs
.push_back(Minus
);
102 StrRefArgs
.push_back(second
);
104 // Now process the canonical list and fill in the vector of uint32_t's. If
105 // there is any error, return false and the client should ignore wp_ids.
106 uint32_t beg
, end
, id
;
107 size_t size
= StrRefArgs
.size();
108 bool in_range
= false;
109 for (i
= 0; i
< size
; ++i
) {
110 llvm::StringRef Arg
= StrRefArgs
[i
];
112 // Look for the 'end' of the range. Note StringRef::getAsInteger()
113 // returns true to signify error while parsing.
114 if (Arg
.getAsInteger(0, end
))
116 // Found a range! Now append the elements.
117 for (id
= beg
; id
<= end
; ++id
)
118 wp_ids
.push_back(id
);
122 if (i
< (size
- 1) && StrRefArgs
[i
+ 1] == Minus
) {
123 if (Arg
.getAsInteger(0, beg
))
125 // Turn on the in_range flag, we are looking for end of range next.
130 // Otherwise, we have a simple ID. Just append it.
131 if (Arg
.getAsInteger(0, beg
))
133 wp_ids
.push_back(beg
);
136 // It is an error if after the loop, we're still in_range.
140 // CommandObjectWatchpointList
142 // CommandObjectWatchpointList::Options
143 #pragma mark List::CommandOptions
144 #define LLDB_OPTIONS_watchpoint_list
145 #include "CommandOptions.inc"
149 class CommandObjectWatchpointList
: public CommandObjectParsed
{
151 CommandObjectWatchpointList(CommandInterpreter
&interpreter
)
152 : CommandObjectParsed(
153 interpreter
, "watchpoint list",
154 "List all watchpoints at configurable levels of detail.", nullptr,
155 eCommandRequiresTarget
) {
156 CommandArgumentEntry arg
;
157 CommandObject::AddIDsArgumentData(arg
, eArgTypeWatchpointID
,
158 eArgTypeWatchpointIDRange
);
159 // Add the entry for the first argument for this command to the object's
161 m_arguments
.push_back(arg
);
164 ~CommandObjectWatchpointList() override
= default;
166 Options
*GetOptions() override
{ return &m_options
; }
168 class CommandOptions
: public Options
{
170 CommandOptions() = default;
172 ~CommandOptions() override
= default;
174 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
175 ExecutionContext
*execution_context
) override
{
177 const int short_option
= m_getopt_table
[option_idx
].val
;
179 switch (short_option
) {
181 m_level
= lldb::eDescriptionLevelBrief
;
184 m_level
= lldb::eDescriptionLevelFull
;
187 m_level
= lldb::eDescriptionLevelVerbose
;
190 llvm_unreachable("Unimplemented option");
196 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
197 m_level
= lldb::eDescriptionLevelFull
;
200 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
201 return llvm::ArrayRef(g_watchpoint_list_options
);
204 // Instance variables to hold the values for command options.
206 lldb::DescriptionLevel m_level
= lldb::eDescriptionLevelBrief
;
210 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
211 Target
*target
= &GetSelectedTarget();
213 if (target
->GetProcessSP() && target
->GetProcessSP()->IsAlive()) {
214 std::optional
<uint32_t> num_supported_hardware_watchpoints
=
215 target
->GetProcessSP()->GetWatchpointSlotCount();
217 if (num_supported_hardware_watchpoints
)
218 result
.AppendMessageWithFormat(
219 "Number of supported hardware watchpoints: %u\n",
220 *num_supported_hardware_watchpoints
);
223 const WatchpointList
&watchpoints
= target
->GetWatchpointList();
225 std::unique_lock
<std::recursive_mutex
> lock
;
226 target
->GetWatchpointList().GetListMutex(lock
);
228 size_t num_watchpoints
= watchpoints
.GetSize();
230 if (num_watchpoints
== 0) {
231 result
.AppendMessage("No watchpoints currently set.");
232 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
236 Stream
&output_stream
= result
.GetOutputStream();
238 if (command
.GetArgumentCount() == 0) {
239 // No watchpoint selected; show info about all currently set watchpoints.
240 result
.AppendMessage("Current watchpoints:");
241 for (size_t i
= 0; i
< num_watchpoints
; ++i
) {
242 WatchpointSP watch_sp
= watchpoints
.GetByIndex(i
);
243 AddWatchpointDescription(output_stream
, *watch_sp
, m_options
.m_level
);
245 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
247 // Particular watchpoints selected; enable them.
248 std::vector
<uint32_t> wp_ids
;
249 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
250 target
, command
, wp_ids
)) {
251 result
.AppendError("Invalid watchpoints specification.");
255 const size_t size
= wp_ids
.size();
256 for (size_t i
= 0; i
< size
; ++i
) {
257 WatchpointSP watch_sp
= watchpoints
.FindByID(wp_ids
[i
]);
259 AddWatchpointDescription(output_stream
, *watch_sp
, m_options
.m_level
);
260 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
266 CommandOptions m_options
;
269 // CommandObjectWatchpointEnable
272 class CommandObjectWatchpointEnable
: public CommandObjectParsed
{
274 CommandObjectWatchpointEnable(CommandInterpreter
&interpreter
)
275 : CommandObjectParsed(interpreter
, "enable",
276 "Enable the specified disabled watchpoint(s). If "
277 "no watchpoints are specified, enable all of them.",
278 nullptr, eCommandRequiresTarget
) {
279 CommandArgumentEntry arg
;
280 CommandObject::AddIDsArgumentData(arg
, eArgTypeWatchpointID
,
281 eArgTypeWatchpointIDRange
);
282 // Add the entry for the first argument for this command to the object's
284 m_arguments
.push_back(arg
);
287 ~CommandObjectWatchpointEnable() override
= default;
290 HandleArgumentCompletion(CompletionRequest
&request
,
291 OptionElementVector
&opt_element_vector
) override
{
292 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
293 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
298 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
299 Target
*target
= &GetSelectedTarget();
300 if (!CheckTargetForWatchpointOperations(target
, result
))
303 std::unique_lock
<std::recursive_mutex
> lock
;
304 target
->GetWatchpointList().GetListMutex(lock
);
306 const WatchpointList
&watchpoints
= target
->GetWatchpointList();
308 size_t num_watchpoints
= watchpoints
.GetSize();
310 if (num_watchpoints
== 0) {
311 result
.AppendError("No watchpoints exist to be enabled.");
315 if (command
.GetArgumentCount() == 0) {
316 // No watchpoint selected; enable all currently set watchpoints.
317 target
->EnableAllWatchpoints();
318 result
.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64
320 (uint64_t)num_watchpoints
);
321 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
323 // Particular watchpoints selected; enable them.
324 std::vector
<uint32_t> wp_ids
;
325 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
326 target
, command
, wp_ids
)) {
327 result
.AppendError("Invalid watchpoints specification.");
332 const size_t size
= wp_ids
.size();
333 for (size_t i
= 0; i
< size
; ++i
)
334 if (target
->EnableWatchpointByID(wp_ids
[i
]))
336 result
.AppendMessageWithFormat("%d watchpoints enabled.\n", count
);
337 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
342 // CommandObjectWatchpointDisable
345 class CommandObjectWatchpointDisable
: public CommandObjectParsed
{
347 CommandObjectWatchpointDisable(CommandInterpreter
&interpreter
)
348 : CommandObjectParsed(interpreter
, "watchpoint disable",
349 "Disable the specified watchpoint(s) without "
350 "removing it/them. If no watchpoints are "
351 "specified, disable them all.",
352 nullptr, eCommandRequiresTarget
) {
353 CommandArgumentEntry arg
;
354 CommandObject::AddIDsArgumentData(arg
, eArgTypeWatchpointID
,
355 eArgTypeWatchpointIDRange
);
356 // Add the entry for the first argument for this command to the object's
358 m_arguments
.push_back(arg
);
361 ~CommandObjectWatchpointDisable() override
= default;
364 HandleArgumentCompletion(CompletionRequest
&request
,
365 OptionElementVector
&opt_element_vector
) override
{
366 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
367 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
372 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
373 Target
*target
= &GetSelectedTarget();
374 if (!CheckTargetForWatchpointOperations(target
, result
))
377 std::unique_lock
<std::recursive_mutex
> lock
;
378 target
->GetWatchpointList().GetListMutex(lock
);
380 const WatchpointList
&watchpoints
= target
->GetWatchpointList();
381 size_t num_watchpoints
= watchpoints
.GetSize();
383 if (num_watchpoints
== 0) {
384 result
.AppendError("No watchpoints exist to be disabled.");
388 if (command
.GetArgumentCount() == 0) {
389 // No watchpoint selected; disable all currently set watchpoints.
390 if (target
->DisableAllWatchpoints()) {
391 result
.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64
393 (uint64_t)num_watchpoints
);
394 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
396 result
.AppendError("Disable all watchpoints failed\n");
399 // Particular watchpoints selected; disable them.
400 std::vector
<uint32_t> wp_ids
;
401 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
402 target
, command
, wp_ids
)) {
403 result
.AppendError("Invalid watchpoints specification.");
408 const size_t size
= wp_ids
.size();
409 for (size_t i
= 0; i
< size
; ++i
)
410 if (target
->DisableWatchpointByID(wp_ids
[i
]))
412 result
.AppendMessageWithFormat("%d watchpoints disabled.\n", count
);
413 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
418 // CommandObjectWatchpointDelete
419 #define LLDB_OPTIONS_watchpoint_delete
420 #include "CommandOptions.inc"
422 // CommandObjectWatchpointDelete
425 class CommandObjectWatchpointDelete
: public CommandObjectParsed
{
427 CommandObjectWatchpointDelete(CommandInterpreter
&interpreter
)
428 : CommandObjectParsed(interpreter
, "watchpoint delete",
429 "Delete the specified watchpoint(s). If no "
430 "watchpoints are specified, delete them all.",
431 nullptr, eCommandRequiresTarget
) {
432 CommandArgumentEntry arg
;
433 CommandObject::AddIDsArgumentData(arg
, eArgTypeWatchpointID
,
434 eArgTypeWatchpointIDRange
);
435 // Add the entry for the first argument for this command to the object's
437 m_arguments
.push_back(arg
);
440 ~CommandObjectWatchpointDelete() override
= default;
443 HandleArgumentCompletion(CompletionRequest
&request
,
444 OptionElementVector
&opt_element_vector
) override
{
445 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
446 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
450 Options
*GetOptions() override
{ return &m_options
; }
452 class CommandOptions
: public Options
{
454 CommandOptions() = default;
456 ~CommandOptions() override
= default;
458 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
459 ExecutionContext
*execution_context
) override
{
460 const int short_option
= m_getopt_table
[option_idx
].val
;
462 switch (short_option
) {
467 llvm_unreachable("Unimplemented option");
473 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
477 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
478 return llvm::ArrayRef(g_watchpoint_delete_options
);
481 // Instance variables to hold the values for command options.
482 bool m_force
= false;
486 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
487 Target
*target
= &GetSelectedTarget();
488 if (!CheckTargetForWatchpointOperations(target
, result
))
491 std::unique_lock
<std::recursive_mutex
> lock
;
492 target
->GetWatchpointList().GetListMutex(lock
);
494 const WatchpointList
&watchpoints
= target
->GetWatchpointList();
496 size_t num_watchpoints
= watchpoints
.GetSize();
498 if (num_watchpoints
== 0) {
499 result
.AppendError("No watchpoints exist to be deleted.");
503 if (command
.empty()) {
504 if (!m_options
.m_force
&&
505 !m_interpreter
.Confirm(
506 "About to delete all watchpoints, do you want to do that?",
508 result
.AppendMessage("Operation cancelled...");
510 target
->RemoveAllWatchpoints();
511 result
.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
513 (uint64_t)num_watchpoints
);
515 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
519 // Particular watchpoints selected; delete them.
520 std::vector
<uint32_t> wp_ids
;
521 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target
, command
,
523 result
.AppendError("Invalid watchpoints specification.");
528 const size_t size
= wp_ids
.size();
529 for (size_t i
= 0; i
< size
; ++i
)
530 if (target
->RemoveWatchpointByID(wp_ids
[i
]))
532 result
.AppendMessageWithFormat("%d watchpoints deleted.\n", count
);
533 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
537 CommandOptions m_options
;
540 // CommandObjectWatchpointIgnore
542 #pragma mark Ignore::CommandOptions
543 #define LLDB_OPTIONS_watchpoint_ignore
544 #include "CommandOptions.inc"
546 class CommandObjectWatchpointIgnore
: public CommandObjectParsed
{
548 CommandObjectWatchpointIgnore(CommandInterpreter
&interpreter
)
549 : CommandObjectParsed(interpreter
, "watchpoint ignore",
550 "Set ignore count on the specified watchpoint(s). "
551 "If no watchpoints are specified, set them all.",
552 nullptr, eCommandRequiresTarget
) {
553 CommandArgumentEntry arg
;
554 CommandObject::AddIDsArgumentData(arg
, eArgTypeWatchpointID
,
555 eArgTypeWatchpointIDRange
);
556 // Add the entry for the first argument for this command to the object's
558 m_arguments
.push_back(arg
);
561 ~CommandObjectWatchpointIgnore() override
= default;
564 HandleArgumentCompletion(CompletionRequest
&request
,
565 OptionElementVector
&opt_element_vector
) override
{
566 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
567 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
571 Options
*GetOptions() override
{ return &m_options
; }
573 class CommandOptions
: public Options
{
575 CommandOptions() = default;
577 ~CommandOptions() override
= default;
579 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
580 ExecutionContext
*execution_context
) override
{
582 const int short_option
= m_getopt_table
[option_idx
].val
;
584 switch (short_option
) {
586 if (option_arg
.getAsInteger(0, m_ignore_count
))
587 error
.SetErrorStringWithFormat("invalid ignore count '%s'",
588 option_arg
.str().c_str());
591 llvm_unreachable("Unimplemented option");
597 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
601 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
602 return llvm::ArrayRef(g_watchpoint_ignore_options
);
605 // Instance variables to hold the values for command options.
607 uint32_t m_ignore_count
= 0;
611 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
612 Target
*target
= &GetSelectedTarget();
613 if (!CheckTargetForWatchpointOperations(target
, result
))
616 std::unique_lock
<std::recursive_mutex
> lock
;
617 target
->GetWatchpointList().GetListMutex(lock
);
619 const WatchpointList
&watchpoints
= target
->GetWatchpointList();
621 size_t num_watchpoints
= watchpoints
.GetSize();
623 if (num_watchpoints
== 0) {
624 result
.AppendError("No watchpoints exist to be ignored.");
628 if (command
.GetArgumentCount() == 0) {
629 target
->IgnoreAllWatchpoints(m_options
.m_ignore_count
);
630 result
.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
632 (uint64_t)num_watchpoints
);
633 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
635 // Particular watchpoints selected; ignore them.
636 std::vector
<uint32_t> wp_ids
;
637 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
638 target
, command
, wp_ids
)) {
639 result
.AppendError("Invalid watchpoints specification.");
644 const size_t size
= wp_ids
.size();
645 for (size_t i
= 0; i
< size
; ++i
)
646 if (target
->IgnoreWatchpointByID(wp_ids
[i
], m_options
.m_ignore_count
))
648 result
.AppendMessageWithFormat("%d watchpoints ignored.\n", count
);
649 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
654 CommandOptions m_options
;
657 // CommandObjectWatchpointModify
659 #pragma mark Modify::CommandOptions
660 #define LLDB_OPTIONS_watchpoint_modify
661 #include "CommandOptions.inc"
665 class CommandObjectWatchpointModify
: public CommandObjectParsed
{
667 CommandObjectWatchpointModify(CommandInterpreter
&interpreter
)
668 : CommandObjectParsed(
669 interpreter
, "watchpoint modify",
670 "Modify the options on a watchpoint or set of watchpoints in the "
672 "If no watchpoint is specified, act on the last created "
674 "Passing an empty argument clears the modification.",
675 nullptr, eCommandRequiresTarget
) {
676 CommandArgumentEntry arg
;
677 CommandObject::AddIDsArgumentData(arg
, eArgTypeWatchpointID
,
678 eArgTypeWatchpointIDRange
);
679 // Add the entry for the first argument for this command to the object's
681 m_arguments
.push_back(arg
);
684 ~CommandObjectWatchpointModify() override
= default;
687 HandleArgumentCompletion(CompletionRequest
&request
,
688 OptionElementVector
&opt_element_vector
) override
{
689 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
690 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
694 Options
*GetOptions() override
{ return &m_options
; }
696 class CommandOptions
: public Options
{
698 CommandOptions() = default;
700 ~CommandOptions() override
= default;
702 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
703 ExecutionContext
*execution_context
) override
{
705 const int short_option
= m_getopt_table
[option_idx
].val
;
707 switch (short_option
) {
709 m_condition
= std::string(option_arg
);
710 m_condition_passed
= true;
713 llvm_unreachable("Unimplemented option");
719 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
721 m_condition_passed
= false;
724 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
725 return llvm::ArrayRef(g_watchpoint_modify_options
);
728 // Instance variables to hold the values for command options.
730 std::string m_condition
;
731 bool m_condition_passed
= false;
735 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
736 Target
*target
= &GetSelectedTarget();
737 if (!CheckTargetForWatchpointOperations(target
, result
))
740 std::unique_lock
<std::recursive_mutex
> lock
;
741 target
->GetWatchpointList().GetListMutex(lock
);
743 const WatchpointList
&watchpoints
= target
->GetWatchpointList();
745 size_t num_watchpoints
= watchpoints
.GetSize();
747 if (num_watchpoints
== 0) {
748 result
.AppendError("No watchpoints exist to be modified.");
752 if (command
.GetArgumentCount() == 0) {
753 WatchpointSP watch_sp
= target
->GetLastCreatedWatchpoint();
754 watch_sp
->SetCondition(m_options
.m_condition
.c_str());
755 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
757 // Particular watchpoints selected; set condition on them.
758 std::vector
<uint32_t> wp_ids
;
759 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
760 target
, command
, wp_ids
)) {
761 result
.AppendError("Invalid watchpoints specification.");
766 const size_t size
= wp_ids
.size();
767 for (size_t i
= 0; i
< size
; ++i
) {
768 WatchpointSP watch_sp
= watchpoints
.FindByID(wp_ids
[i
]);
770 watch_sp
->SetCondition(m_options
.m_condition
.c_str());
774 result
.AppendMessageWithFormat("%d watchpoints modified.\n", count
);
775 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
780 CommandOptions m_options
;
783 // CommandObjectWatchpointSetVariable
784 #pragma mark SetVariable
786 class CommandObjectWatchpointSetVariable
: public CommandObjectParsed
{
788 CommandObjectWatchpointSetVariable(CommandInterpreter
&interpreter
)
789 : CommandObjectParsed(
790 interpreter
, "watchpoint set variable",
791 "Set a watchpoint on a variable. "
792 "Use the '-w' option to specify the type of watchpoint and "
793 "the '-s' option to specify the byte size to watch for. "
794 "If no '-w' option is specified, it defaults to modify. "
795 "If no '-s' option is specified, it defaults to the variable's "
797 "Note that there are limited hardware resources for watchpoints. "
798 "If watchpoint setting fails, consider disable/delete existing "
800 "to free up resources.",
802 eCommandRequiresFrame
| eCommandTryTargetAPILock
|
803 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
808 (lldb) watchpoint set variable -w read_write my_global_var
811 " Watches my_global_var for read/write access, with the region to watch \
812 corresponding to the byte size of the data type.");
814 CommandArgumentEntry arg
;
815 CommandArgumentData var_name_arg
;
817 // Define the only variant of this arg.
818 var_name_arg
.arg_type
= eArgTypeVarName
;
819 var_name_arg
.arg_repetition
= eArgRepeatPlain
;
821 // Push the variant into the argument entry.
822 arg
.push_back(var_name_arg
);
824 // Push the data for the only argument into the m_arguments vector.
825 m_arguments
.push_back(arg
);
827 // Absorb the '-w' and '-s' options into our option group.
828 m_option_group
.Append(&m_option_watchpoint
, LLDB_OPT_SET_1
, LLDB_OPT_SET_1
);
829 m_option_group
.Finalize();
832 ~CommandObjectWatchpointSetVariable() override
= default;
835 HandleArgumentCompletion(CompletionRequest
&request
,
836 OptionElementVector
&opt_element_vector
) override
{
837 if (request
.GetCursorIndex() != 0)
839 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
840 GetCommandInterpreter(), lldb::eVariablePathCompletion
, request
,
844 Options
*GetOptions() override
{ return &m_option_group
; }
847 static size_t GetVariableCallback(void *baton
, const char *name
,
848 VariableList
&variable_list
) {
849 size_t old_size
= variable_list
.GetSize();
850 Target
*target
= static_cast<Target
*>(baton
);
852 target
->GetImages().FindGlobalVariables(ConstString(name
), UINT32_MAX
,
854 return variable_list
.GetSize() - old_size
;
857 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
858 Target
*target
= GetDebugger().GetSelectedTarget().get();
859 StackFrame
*frame
= m_exe_ctx
.GetFramePtr();
861 // If no argument is present, issue an error message. There's no way to
863 if (command
.GetArgumentCount() <= 0) {
864 result
.AppendError("required argument missing; "
865 "specify your program variable to watch for");
869 // If no '-w' is specified, default to '-w modify'.
870 if (!m_option_watchpoint
.watch_type_specified
) {
871 m_option_watchpoint
.watch_type
= OptionGroupWatchpoint::eWatchModify
;
874 // We passed the sanity check for the command. Proceed to set the
876 lldb::addr_t addr
= 0;
880 ValueObjectSP valobj_sp
;
881 Stream
&output_stream
= result
.GetOutputStream();
883 // A simple watch variable gesture allows only one argument.
884 if (command
.GetArgumentCount() != 1) {
885 result
.AppendError("specify exactly one variable to watch for");
889 // Things have checked out ok...
891 uint32_t expr_path_options
=
892 StackFrame::eExpressionPathOptionCheckPtrVsMember
|
893 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess
;
894 valobj_sp
= frame
->GetValueForVariableExpressionPath(
895 command
.GetArgumentAtIndex(0), eNoDynamicValues
, expr_path_options
,
899 // Not in the frame; let's check the globals.
901 VariableList variable_list
;
902 ValueObjectList valobj_list
;
904 Status
error(Variable::GetValuesForVariableExpressionPath(
905 command
.GetArgumentAtIndex(0),
906 m_exe_ctx
.GetBestExecutionContextScope(), GetVariableCallback
, target
,
907 variable_list
, valobj_list
));
909 if (valobj_list
.GetSize())
910 valobj_sp
= valobj_list
.GetValueObjectAtIndex(0);
913 CompilerType compiler_type
;
916 AddressType addr_type
;
917 addr
= valobj_sp
->GetAddressOf(false, &addr_type
);
918 if (addr_type
== eAddressTypeLoad
) {
919 // We're in business.
920 // Find out the size of this variable.
921 size
= m_option_watchpoint
.watch_size
== 0
922 ? valobj_sp
->GetByteSize().value_or(0)
923 : m_option_watchpoint
.watch_size
;
925 compiler_type
= valobj_sp
->GetCompilerType();
927 const char *error_cstr
= error
.AsCString(nullptr);
929 result
.AppendError(error_cstr
);
931 result
.AppendErrorWithFormat("unable to find any variable "
932 "expression path that matches '%s'",
933 command
.GetArgumentAtIndex(0));
937 // Now it's time to create the watchpoint.
938 uint32_t watch_type
= 0;
939 switch (m_option_watchpoint
.watch_type
) {
940 case OptionGroupWatchpoint::eWatchModify
:
941 watch_type
|= LLDB_WATCH_TYPE_MODIFY
;
943 case OptionGroupWatchpoint::eWatchRead
:
944 watch_type
|= LLDB_WATCH_TYPE_READ
;
946 case OptionGroupWatchpoint::eWatchReadWrite
:
947 watch_type
|= LLDB_WATCH_TYPE_READ
| LLDB_WATCH_TYPE_WRITE
;
949 case OptionGroupWatchpoint::eWatchWrite
:
950 watch_type
|= LLDB_WATCH_TYPE_WRITE
;
952 case OptionGroupWatchpoint::eWatchInvalid
:
957 WatchpointSP watch_sp
=
958 target
->CreateWatchpoint(addr
, size
, &compiler_type
, watch_type
, error
);
960 result
.AppendErrorWithFormat(
961 "Watchpoint creation failed (addr=0x%" PRIx64
", size=%" PRIu64
962 ", variable expression='%s').\n",
963 addr
, static_cast<uint64_t>(size
), command
.GetArgumentAtIndex(0));
964 if (const char *error_message
= error
.AsCString(nullptr))
965 result
.AppendError(error_message
);
969 watch_sp
->SetWatchSpec(command
.GetArgumentAtIndex(0));
970 watch_sp
->SetWatchVariable(true);
972 if (var_sp
->GetDeclaration().GetFile()) {
974 // True to show fullpath for declaration file.
975 var_sp
->GetDeclaration().DumpStopContext(&ss
, true);
976 watch_sp
->SetDeclInfo(std::string(ss
.GetString()));
978 if (var_sp
->GetScope() == eValueTypeVariableLocal
)
979 watch_sp
->SetupVariableWatchpointDisabler(m_exe_ctx
.GetFrameSP());
981 output_stream
.Printf("Watchpoint created: ");
982 watch_sp
->GetDescription(&output_stream
, lldb::eDescriptionLevelFull
);
984 result
.SetStatus(eReturnStatusSuccessFinishResult
);
988 OptionGroupOptions m_option_group
;
989 OptionGroupWatchpoint m_option_watchpoint
;
992 // CommandObjectWatchpointSetExpression
995 class CommandObjectWatchpointSetExpression
: public CommandObjectRaw
{
997 CommandObjectWatchpointSetExpression(CommandInterpreter
&interpreter
)
999 interpreter
, "watchpoint set expression",
1000 "Set a watchpoint on an address by supplying an expression. "
1001 "Use the '-l' option to specify the language of the expression. "
1002 "Use the '-w' option to specify the type of watchpoint and "
1003 "the '-s' option to specify the byte size to watch for. "
1004 "If no '-w' option is specified, it defaults to modify. "
1005 "If no '-s' option is specified, it defaults to the target's "
1006 "pointer byte size. "
1007 "Note that there are limited hardware resources for watchpoints. "
1008 "If watchpoint setting fails, consider disable/delete existing "
1010 "to free up resources.",
1012 eCommandRequiresFrame
| eCommandTryTargetAPILock
|
1013 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
1018 (lldb) watchpoint set expression -w modify -s 1 -- foo + 32
1020 Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
1022 CommandArgumentEntry arg
;
1023 CommandArgumentData expression_arg
;
1025 // Define the only variant of this arg.
1026 expression_arg
.arg_type
= eArgTypeExpression
;
1027 expression_arg
.arg_repetition
= eArgRepeatPlain
;
1029 // Push the only variant into the argument entry.
1030 arg
.push_back(expression_arg
);
1032 // Push the data for the only argument into the m_arguments vector.
1033 m_arguments
.push_back(arg
);
1035 // Absorb the '-w' and '-s' options into our option group.
1036 m_option_group
.Append(&m_option_watchpoint
, LLDB_OPT_SET_ALL
,
1038 m_option_group
.Finalize();
1041 ~CommandObjectWatchpointSetExpression() override
= default;
1043 // Overrides base class's behavior where WantsCompletion =
1044 // !WantsRawCommandString.
1045 bool WantsCompletion() override
{ return true; }
1047 Options
*GetOptions() override
{ return &m_option_group
; }
1050 void DoExecute(llvm::StringRef raw_command
,
1051 CommandReturnObject
&result
) override
{
1052 auto exe_ctx
= GetCommandInterpreter().GetExecutionContext();
1053 m_option_group
.NotifyOptionParsingStarting(
1054 &exe_ctx
); // This is a raw command, so notify the option group
1056 Target
*target
= GetDebugger().GetSelectedTarget().get();
1057 StackFrame
*frame
= m_exe_ctx
.GetFramePtr();
1059 OptionsWithRaw
args(raw_command
);
1061 llvm::StringRef expr
= args
.GetRawPart();
1064 if (!ParseOptionsAndNotify(args
.GetArgs(), result
, m_option_group
,
1068 // If no argument is present, issue an error message. There's no way to
1069 // set a watchpoint.
1070 if (raw_command
.trim().empty()) {
1071 result
.AppendError("required argument missing; specify an expression "
1072 "to evaluate into the address to watch for");
1076 // If no '-w' is specified, default to '-w write'.
1077 if (!m_option_watchpoint
.watch_type_specified
) {
1078 m_option_watchpoint
.watch_type
= OptionGroupWatchpoint::eWatchModify
;
1081 // We passed the sanity check for the command. Proceed to set the
1083 lldb::addr_t addr
= 0;
1086 ValueObjectSP valobj_sp
;
1088 // Use expression evaluation to arrive at the address to watch.
1089 EvaluateExpressionOptions options
;
1090 options
.SetCoerceToId(false);
1091 options
.SetUnwindOnError(true);
1092 options
.SetKeepInMemory(false);
1093 options
.SetTryAllThreads(true);
1094 options
.SetTimeout(std::nullopt
);
1095 if (m_option_watchpoint
.language_type
!= eLanguageTypeUnknown
)
1096 options
.SetLanguage(m_option_watchpoint
.language_type
);
1098 ExpressionResults expr_result
=
1099 target
->EvaluateExpression(expr
, frame
, valobj_sp
, options
);
1100 if (expr_result
!= eExpressionCompleted
) {
1101 result
.AppendError("expression evaluation of address to watch failed");
1102 result
.AppendErrorWithFormat("expression evaluated: \n%s", expr
.data());
1103 if (valobj_sp
&& !valobj_sp
->GetError().Success())
1104 result
.AppendError(valobj_sp
->GetError().AsCString());
1108 // Get the address to watch.
1109 bool success
= false;
1110 addr
= valobj_sp
->GetValueAsUnsigned(0, &success
);
1112 result
.AppendError("expression did not evaluate to an address");
1116 if (m_option_watchpoint
.watch_size
!= 0)
1117 size
= m_option_watchpoint
.watch_size
;
1119 size
= target
->GetArchitecture().GetAddressByteSize();
1121 // Now it's time to create the watchpoint.
1122 uint32_t watch_type
;
1123 switch (m_option_watchpoint
.watch_type
) {
1124 case OptionGroupWatchpoint::eWatchRead
:
1125 watch_type
= LLDB_WATCH_TYPE_READ
;
1127 case OptionGroupWatchpoint::eWatchWrite
:
1128 watch_type
= LLDB_WATCH_TYPE_WRITE
;
1130 case OptionGroupWatchpoint::eWatchModify
:
1131 watch_type
= LLDB_WATCH_TYPE_MODIFY
;
1133 case OptionGroupWatchpoint::eWatchReadWrite
:
1134 watch_type
= LLDB_WATCH_TYPE_READ
| LLDB_WATCH_TYPE_WRITE
;
1137 watch_type
= LLDB_WATCH_TYPE_MODIFY
;
1140 // Fetch the type from the value object, the type of the watched object is
1142 /// of the expression, so convert to that if we found a valid type.
1143 CompilerType
compiler_type(valobj_sp
->GetCompilerType());
1146 WatchpointSP watch_sp
=
1147 target
->CreateWatchpoint(addr
, size
, &compiler_type
, watch_type
, error
);
1149 watch_sp
->SetWatchSpec(std::string(expr
));
1150 Stream
&output_stream
= result
.GetOutputStream();
1151 output_stream
.Printf("Watchpoint created: ");
1152 watch_sp
->GetDescription(&output_stream
, lldb::eDescriptionLevelFull
);
1153 output_stream
.EOL();
1154 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1156 result
.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
1157 ", size=%" PRIu64
").\n",
1158 addr
, (uint64_t)size
);
1159 if (error
.AsCString(nullptr))
1160 result
.AppendError(error
.AsCString());
1165 OptionGroupOptions m_option_group
;
1166 OptionGroupWatchpoint m_option_watchpoint
;
1169 // CommandObjectWatchpointSet
1172 class CommandObjectWatchpointSet
: public CommandObjectMultiword
{
1174 CommandObjectWatchpointSet(CommandInterpreter
&interpreter
)
1175 : CommandObjectMultiword(
1176 interpreter
, "watchpoint set", "Commands for setting a watchpoint.",
1177 "watchpoint set <subcommand> [<subcommand-options>]") {
1181 CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter
)));
1184 CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter
)));
1187 ~CommandObjectWatchpointSet() override
= default;
1190 // CommandObjectMultiwordWatchpoint
1191 #pragma mark MultiwordWatchpoint
1193 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(
1194 CommandInterpreter
&interpreter
)
1195 : CommandObjectMultiword(interpreter
, "watchpoint",
1196 "Commands for operating on watchpoints.",
1197 "watchpoint <subcommand> [<command-options>]") {
1198 CommandObjectSP
list_command_object(
1199 new CommandObjectWatchpointList(interpreter
));
1200 CommandObjectSP
enable_command_object(
1201 new CommandObjectWatchpointEnable(interpreter
));
1202 CommandObjectSP
disable_command_object(
1203 new CommandObjectWatchpointDisable(interpreter
));
1204 CommandObjectSP
delete_command_object(
1205 new CommandObjectWatchpointDelete(interpreter
));
1206 CommandObjectSP
ignore_command_object(
1207 new CommandObjectWatchpointIgnore(interpreter
));
1208 CommandObjectSP
command_command_object(
1209 new CommandObjectWatchpointCommand(interpreter
));
1210 CommandObjectSP
modify_command_object(
1211 new CommandObjectWatchpointModify(interpreter
));
1212 CommandObjectSP
set_command_object(
1213 new CommandObjectWatchpointSet(interpreter
));
1215 list_command_object
->SetCommandName("watchpoint list");
1216 enable_command_object
->SetCommandName("watchpoint enable");
1217 disable_command_object
->SetCommandName("watchpoint disable");
1218 delete_command_object
->SetCommandName("watchpoint delete");
1219 ignore_command_object
->SetCommandName("watchpoint ignore");
1220 command_command_object
->SetCommandName("watchpoint command");
1221 modify_command_object
->SetCommandName("watchpoint modify");
1222 set_command_object
->SetCommandName("watchpoint set");
1224 LoadSubCommand("list", list_command_object
);
1225 LoadSubCommand("enable", enable_command_object
);
1226 LoadSubCommand("disable", disable_command_object
);
1227 LoadSubCommand("delete", delete_command_object
);
1228 LoadSubCommand("ignore", ignore_command_object
);
1229 LoadSubCommand("command", command_command_object
);
1230 LoadSubCommand("modify", modify_command_object
);
1231 LoadSubCommand("set", set_command_object
);
1234 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default;