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/Host/OptionParser.h"
20 #include "lldb/Interpreter/CommandInterpreter.h"
21 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
22 #include "lldb/Interpreter/CommandReturnObject.h"
23 #include "lldb/Symbol/Function.h"
24 #include "lldb/Symbol/Variable.h"
25 #include "lldb/Symbol/VariableList.h"
26 #include "lldb/Target/StackFrame.h"
27 #include "lldb/Target/Target.h"
28 #include "lldb/Utility/StreamString.h"
29 #include "lldb/ValueObject/ValueObject.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 WatchpointSP watch_sp
= target
.GetLastCreatedWatchpoint();
75 wp_ids
.push_back(watch_sp
->GetID());
81 llvm::StringRef
Minus("-");
82 std::vector
<llvm::StringRef
> StrRefArgs
;
83 llvm::StringRef first
;
84 llvm::StringRef second
;
87 // Go through the arguments and make a canonical form of arg list containing
88 // only numbers with possible "-" in between.
89 for (auto &entry
: args
.entries()) {
90 if ((idx
= WithRSAIndex(entry
.ref())) == -1) {
91 StrRefArgs
.push_back(entry
.ref());
94 // The Arg contains the range specifier, split it, then.
95 std::tie(first
, second
) = entry
.ref().split(RSA
[idx
]);
97 StrRefArgs
.push_back(first
);
98 StrRefArgs
.push_back(Minus
);
100 StrRefArgs
.push_back(second
);
102 // Now process the canonical list and fill in the vector of uint32_t's. If
103 // there is any error, return false and the client should ignore wp_ids.
104 uint32_t beg
, end
, id
;
105 size_t size
= StrRefArgs
.size();
106 bool in_range
= false;
107 for (i
= 0; i
< size
; ++i
) {
108 llvm::StringRef Arg
= StrRefArgs
[i
];
110 // Look for the 'end' of the range. Note StringRef::getAsInteger()
111 // returns true to signify error while parsing.
112 if (Arg
.getAsInteger(0, end
))
114 // Found a range! Now append the elements.
115 for (id
= beg
; id
<= end
; ++id
)
116 wp_ids
.push_back(id
);
120 if (i
< (size
- 1) && StrRefArgs
[i
+ 1] == Minus
) {
121 if (Arg
.getAsInteger(0, beg
))
123 // Turn on the in_range flag, we are looking for end of range next.
128 // Otherwise, we have a simple ID. Just append it.
129 if (Arg
.getAsInteger(0, beg
))
131 wp_ids
.push_back(beg
);
134 // It is an error if after the loop, we're still in_range.
138 // CommandObjectWatchpointList
140 // CommandObjectWatchpointList::Options
141 #pragma mark List::CommandOptions
142 #define LLDB_OPTIONS_watchpoint_list
143 #include "CommandOptions.inc"
147 class CommandObjectWatchpointList
: public CommandObjectParsed
{
149 CommandObjectWatchpointList(CommandInterpreter
&interpreter
)
150 : CommandObjectParsed(
151 interpreter
, "watchpoint list",
152 "List all watchpoints at configurable levels of detail.", nullptr,
153 eCommandRequiresTarget
) {
154 CommandObject::AddIDsArgumentData(eWatchpointArgs
);
157 ~CommandObjectWatchpointList() override
= default;
159 Options
*GetOptions() override
{ return &m_options
; }
161 class CommandOptions
: public Options
{
163 CommandOptions() = default;
165 ~CommandOptions() override
= default;
167 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
168 ExecutionContext
*execution_context
) override
{
170 const int short_option
= m_getopt_table
[option_idx
].val
;
172 switch (short_option
) {
174 m_level
= lldb::eDescriptionLevelBrief
;
177 m_level
= lldb::eDescriptionLevelFull
;
180 m_level
= lldb::eDescriptionLevelVerbose
;
183 llvm_unreachable("Unimplemented option");
189 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
190 m_level
= lldb::eDescriptionLevelFull
;
193 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
194 return llvm::ArrayRef(g_watchpoint_list_options
);
197 // Instance variables to hold the values for command options.
199 lldb::DescriptionLevel m_level
= lldb::eDescriptionLevelBrief
;
203 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
204 Target
&target
= GetTarget();
206 if (ProcessSP process_sp
= target
.GetProcessSP()) {
207 if (process_sp
->IsAlive()) {
208 std::optional
<uint32_t> num_supported_hardware_watchpoints
=
209 process_sp
->GetWatchpointSlotCount();
211 if (num_supported_hardware_watchpoints
)
212 result
.AppendMessageWithFormat(
213 "Number of supported hardware watchpoints: %u\n",
214 *num_supported_hardware_watchpoints
);
218 const WatchpointList
&watchpoints
= target
.GetWatchpointList();
220 std::unique_lock
<std::recursive_mutex
> lock
;
221 target
.GetWatchpointList().GetListMutex(lock
);
223 size_t num_watchpoints
= watchpoints
.GetSize();
225 if (num_watchpoints
== 0) {
226 result
.AppendMessage("No watchpoints currently set.");
227 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
231 Stream
&output_stream
= result
.GetOutputStream();
233 if (command
.GetArgumentCount() == 0) {
234 // No watchpoint selected; show info about all currently set watchpoints.
235 result
.AppendMessage("Current watchpoints:");
236 for (size_t i
= 0; i
< num_watchpoints
; ++i
) {
237 WatchpointSP watch_sp
= watchpoints
.GetByIndex(i
);
238 AddWatchpointDescription(output_stream
, *watch_sp
, m_options
.m_level
);
240 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
242 // Particular watchpoints selected; enable them.
243 std::vector
<uint32_t> wp_ids
;
244 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
245 target
, command
, wp_ids
)) {
246 result
.AppendError("Invalid watchpoints specification.");
250 const size_t size
= wp_ids
.size();
251 for (size_t i
= 0; i
< size
; ++i
) {
252 WatchpointSP watch_sp
= watchpoints
.FindByID(wp_ids
[i
]);
254 AddWatchpointDescription(output_stream
, *watch_sp
, m_options
.m_level
);
255 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
261 CommandOptions m_options
;
264 // CommandObjectWatchpointEnable
267 class CommandObjectWatchpointEnable
: public CommandObjectParsed
{
269 CommandObjectWatchpointEnable(CommandInterpreter
&interpreter
)
270 : CommandObjectParsed(interpreter
, "enable",
271 "Enable the specified disabled watchpoint(s). If "
272 "no watchpoints are specified, enable all of them.",
273 nullptr, eCommandRequiresTarget
) {
274 CommandObject::AddIDsArgumentData(eWatchpointArgs
);
277 ~CommandObjectWatchpointEnable() override
= default;
280 HandleArgumentCompletion(CompletionRequest
&request
,
281 OptionElementVector
&opt_element_vector
) override
{
282 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
283 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
288 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
289 Target
&target
= GetTarget();
290 if (!CheckTargetForWatchpointOperations(target
, result
))
293 std::unique_lock
<std::recursive_mutex
> lock
;
294 target
.GetWatchpointList().GetListMutex(lock
);
296 const WatchpointList
&watchpoints
= target
.GetWatchpointList();
298 size_t num_watchpoints
= watchpoints
.GetSize();
300 if (num_watchpoints
== 0) {
301 result
.AppendError("No watchpoints exist to be enabled.");
305 if (command
.GetArgumentCount() == 0) {
306 // No watchpoint selected; enable all currently set watchpoints.
307 target
.EnableAllWatchpoints();
308 result
.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64
310 (uint64_t)num_watchpoints
);
311 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
313 // Particular watchpoints selected; enable them.
314 std::vector
<uint32_t> wp_ids
;
315 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
316 target
, command
, wp_ids
)) {
317 result
.AppendError("Invalid watchpoints specification.");
322 const size_t size
= wp_ids
.size();
323 for (size_t i
= 0; i
< size
; ++i
)
324 if (target
.EnableWatchpointByID(wp_ids
[i
]))
326 result
.AppendMessageWithFormat("%d watchpoints enabled.\n", count
);
327 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
332 // CommandObjectWatchpointDisable
335 class CommandObjectWatchpointDisable
: public CommandObjectParsed
{
337 CommandObjectWatchpointDisable(CommandInterpreter
&interpreter
)
338 : CommandObjectParsed(interpreter
, "watchpoint disable",
339 "Disable the specified watchpoint(s) without "
340 "removing it/them. If no watchpoints are "
341 "specified, disable them all.",
342 nullptr, eCommandRequiresTarget
) {
343 CommandObject::AddIDsArgumentData(eWatchpointArgs
);
346 ~CommandObjectWatchpointDisable() override
= default;
349 HandleArgumentCompletion(CompletionRequest
&request
,
350 OptionElementVector
&opt_element_vector
) override
{
351 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
352 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
357 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
358 Target
&target
= GetTarget();
359 if (!CheckTargetForWatchpointOperations(target
, result
))
362 std::unique_lock
<std::recursive_mutex
> lock
;
363 target
.GetWatchpointList().GetListMutex(lock
);
365 const WatchpointList
&watchpoints
= target
.GetWatchpointList();
366 size_t num_watchpoints
= watchpoints
.GetSize();
368 if (num_watchpoints
== 0) {
369 result
.AppendError("No watchpoints exist to be disabled.");
373 if (command
.GetArgumentCount() == 0) {
374 // No watchpoint selected; disable all currently set watchpoints.
375 if (target
.DisableAllWatchpoints()) {
376 result
.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64
378 (uint64_t)num_watchpoints
);
379 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
381 result
.AppendError("Disable all watchpoints failed\n");
384 // Particular watchpoints selected; disable them.
385 std::vector
<uint32_t> wp_ids
;
386 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
387 target
, command
, wp_ids
)) {
388 result
.AppendError("Invalid watchpoints specification.");
393 const size_t size
= wp_ids
.size();
394 for (size_t i
= 0; i
< size
; ++i
)
395 if (target
.DisableWatchpointByID(wp_ids
[i
]))
397 result
.AppendMessageWithFormat("%d watchpoints disabled.\n", count
);
398 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
403 // CommandObjectWatchpointDelete
404 #define LLDB_OPTIONS_watchpoint_delete
405 #include "CommandOptions.inc"
407 // CommandObjectWatchpointDelete
410 class CommandObjectWatchpointDelete
: public CommandObjectParsed
{
412 CommandObjectWatchpointDelete(CommandInterpreter
&interpreter
)
413 : CommandObjectParsed(interpreter
, "watchpoint delete",
414 "Delete the specified watchpoint(s). If no "
415 "watchpoints are specified, delete them all.",
416 nullptr, eCommandRequiresTarget
) {
417 CommandObject::AddIDsArgumentData(eWatchpointArgs
);
420 ~CommandObjectWatchpointDelete() override
= default;
423 HandleArgumentCompletion(CompletionRequest
&request
,
424 OptionElementVector
&opt_element_vector
) override
{
425 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
426 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
430 Options
*GetOptions() override
{ return &m_options
; }
432 class CommandOptions
: public Options
{
434 CommandOptions() = default;
436 ~CommandOptions() override
= default;
438 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
439 ExecutionContext
*execution_context
) override
{
440 const int short_option
= m_getopt_table
[option_idx
].val
;
442 switch (short_option
) {
447 llvm_unreachable("Unimplemented option");
453 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
457 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
458 return llvm::ArrayRef(g_watchpoint_delete_options
);
461 // Instance variables to hold the values for command options.
462 bool m_force
= false;
466 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
467 Target
&target
= GetTarget();
468 if (!CheckTargetForWatchpointOperations(target
, result
))
471 std::unique_lock
<std::recursive_mutex
> lock
;
472 target
.GetWatchpointList().GetListMutex(lock
);
474 const WatchpointList
&watchpoints
= target
.GetWatchpointList();
476 size_t num_watchpoints
= watchpoints
.GetSize();
478 if (num_watchpoints
== 0) {
479 result
.AppendError("No watchpoints exist to be deleted.");
483 if (command
.empty()) {
484 if (!m_options
.m_force
&&
485 !m_interpreter
.Confirm(
486 "About to delete all watchpoints, do you want to do that?",
488 result
.AppendMessage("Operation cancelled...");
490 target
.RemoveAllWatchpoints();
491 result
.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
493 (uint64_t)num_watchpoints
);
495 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
499 // Particular watchpoints selected; delete them.
500 std::vector
<uint32_t> wp_ids
;
501 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target
, command
,
503 result
.AppendError("Invalid watchpoints specification.");
508 const size_t size
= wp_ids
.size();
509 for (size_t i
= 0; i
< size
; ++i
)
510 if (target
.RemoveWatchpointByID(wp_ids
[i
]))
512 result
.AppendMessageWithFormat("%d watchpoints deleted.\n", count
);
513 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
517 CommandOptions m_options
;
520 // CommandObjectWatchpointIgnore
522 #pragma mark Ignore::CommandOptions
523 #define LLDB_OPTIONS_watchpoint_ignore
524 #include "CommandOptions.inc"
526 class CommandObjectWatchpointIgnore
: public CommandObjectParsed
{
528 CommandObjectWatchpointIgnore(CommandInterpreter
&interpreter
)
529 : CommandObjectParsed(interpreter
, "watchpoint ignore",
530 "Set ignore count on the specified watchpoint(s). "
531 "If no watchpoints are specified, set them all.",
532 nullptr, eCommandRequiresTarget
) {
533 CommandObject::AddIDsArgumentData(eWatchpointArgs
);
536 ~CommandObjectWatchpointIgnore() override
= default;
539 HandleArgumentCompletion(CompletionRequest
&request
,
540 OptionElementVector
&opt_element_vector
) override
{
541 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
542 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
546 Options
*GetOptions() override
{ return &m_options
; }
548 class CommandOptions
: public Options
{
550 CommandOptions() = default;
552 ~CommandOptions() override
= default;
554 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
555 ExecutionContext
*execution_context
) override
{
557 const int short_option
= m_getopt_table
[option_idx
].val
;
559 switch (short_option
) {
561 if (option_arg
.getAsInteger(0, m_ignore_count
))
562 error
= Status::FromErrorStringWithFormat("invalid ignore count '%s'",
563 option_arg
.str().c_str());
566 llvm_unreachable("Unimplemented option");
572 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
576 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
577 return llvm::ArrayRef(g_watchpoint_ignore_options
);
580 // Instance variables to hold the values for command options.
582 uint32_t m_ignore_count
= 0;
586 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
587 Target
&target
= GetTarget();
588 if (!CheckTargetForWatchpointOperations(target
, result
))
591 std::unique_lock
<std::recursive_mutex
> lock
;
592 target
.GetWatchpointList().GetListMutex(lock
);
594 const WatchpointList
&watchpoints
= target
.GetWatchpointList();
596 size_t num_watchpoints
= watchpoints
.GetSize();
598 if (num_watchpoints
== 0) {
599 result
.AppendError("No watchpoints exist to be ignored.");
603 if (command
.GetArgumentCount() == 0) {
604 target
.IgnoreAllWatchpoints(m_options
.m_ignore_count
);
605 result
.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
607 (uint64_t)num_watchpoints
);
608 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
610 // Particular watchpoints selected; ignore them.
611 std::vector
<uint32_t> wp_ids
;
612 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
613 target
, command
, wp_ids
)) {
614 result
.AppendError("Invalid watchpoints specification.");
619 const size_t size
= wp_ids
.size();
620 for (size_t i
= 0; i
< size
; ++i
)
621 if (target
.IgnoreWatchpointByID(wp_ids
[i
], m_options
.m_ignore_count
))
623 result
.AppendMessageWithFormat("%d watchpoints ignored.\n", count
);
624 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
629 CommandOptions m_options
;
632 // CommandObjectWatchpointModify
634 #pragma mark Modify::CommandOptions
635 #define LLDB_OPTIONS_watchpoint_modify
636 #include "CommandOptions.inc"
640 class CommandObjectWatchpointModify
: public CommandObjectParsed
{
642 CommandObjectWatchpointModify(CommandInterpreter
&interpreter
)
643 : CommandObjectParsed(
644 interpreter
, "watchpoint modify",
645 "Modify the options on a watchpoint or set of watchpoints in the "
647 "If no watchpoint is specified, act on the last created "
649 "Passing an empty argument clears the modification.",
650 nullptr, eCommandRequiresTarget
) {
651 CommandObject::AddIDsArgumentData(eWatchpointArgs
);
654 ~CommandObjectWatchpointModify() override
= default;
657 HandleArgumentCompletion(CompletionRequest
&request
,
658 OptionElementVector
&opt_element_vector
) override
{
659 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
660 GetCommandInterpreter(), lldb::eWatchpointIDCompletion
, request
,
664 Options
*GetOptions() override
{ return &m_options
; }
666 class CommandOptions
: public Options
{
668 CommandOptions() = default;
670 ~CommandOptions() override
= default;
672 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
673 ExecutionContext
*execution_context
) override
{
675 const int short_option
= m_getopt_table
[option_idx
].val
;
677 switch (short_option
) {
679 m_condition
= std::string(option_arg
);
680 m_condition_passed
= true;
683 llvm_unreachable("Unimplemented option");
689 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
691 m_condition_passed
= false;
694 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
695 return llvm::ArrayRef(g_watchpoint_modify_options
);
698 // Instance variables to hold the values for command options.
700 std::string m_condition
;
701 bool m_condition_passed
= false;
705 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
706 Target
&target
= GetTarget();
707 if (!CheckTargetForWatchpointOperations(target
, result
))
710 std::unique_lock
<std::recursive_mutex
> lock
;
711 target
.GetWatchpointList().GetListMutex(lock
);
713 const WatchpointList
&watchpoints
= target
.GetWatchpointList();
715 size_t num_watchpoints
= watchpoints
.GetSize();
717 if (num_watchpoints
== 0) {
718 result
.AppendError("No watchpoints exist to be modified.");
722 if (command
.GetArgumentCount() == 0) {
723 WatchpointSP watch_sp
= target
.GetLastCreatedWatchpoint();
724 watch_sp
->SetCondition(m_options
.m_condition
.c_str());
725 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
727 // Particular watchpoints selected; set condition on them.
728 std::vector
<uint32_t> wp_ids
;
729 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
730 target
, command
, wp_ids
)) {
731 result
.AppendError("Invalid watchpoints specification.");
736 const size_t size
= wp_ids
.size();
737 for (size_t i
= 0; i
< size
; ++i
) {
738 WatchpointSP watch_sp
= watchpoints
.FindByID(wp_ids
[i
]);
740 watch_sp
->SetCondition(m_options
.m_condition
.c_str());
744 result
.AppendMessageWithFormat("%d watchpoints modified.\n", count
);
745 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
750 CommandOptions m_options
;
753 // CommandObjectWatchpointSetVariable
754 #pragma mark SetVariable
756 class CommandObjectWatchpointSetVariable
: public CommandObjectParsed
{
758 CommandObjectWatchpointSetVariable(CommandInterpreter
&interpreter
)
759 : CommandObjectParsed(
760 interpreter
, "watchpoint set variable",
761 "Set a watchpoint on a variable. "
762 "Use the '-w' option to specify the type of watchpoint and "
763 "the '-s' option to specify the byte size to watch for. "
764 "If no '-w' option is specified, it defaults to modify. "
765 "If no '-s' option is specified, it defaults to the variable's "
767 "Note that there are limited hardware resources for watchpoints. "
768 "If watchpoint setting fails, consider disable/delete existing "
770 "to free up resources.",
772 eCommandRequiresFrame
| eCommandTryTargetAPILock
|
773 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
778 (lldb) watchpoint set variable -w read_write my_global_var
781 " Watches my_global_var for read/write access, with the region to watch \
782 corresponding to the byte size of the data type.");
784 AddSimpleArgumentList(eArgTypeVarName
);
786 // Absorb the '-w' and '-s' options into our option group.
787 m_option_group
.Append(&m_option_watchpoint
, LLDB_OPT_SET_1
, LLDB_OPT_SET_1
);
788 m_option_group
.Finalize();
791 ~CommandObjectWatchpointSetVariable() override
= default;
793 Options
*GetOptions() override
{ return &m_option_group
; }
796 static size_t GetVariableCallback(void *baton
, const char *name
,
797 VariableList
&variable_list
) {
798 size_t old_size
= variable_list
.GetSize();
799 Target
*target
= static_cast<Target
*>(baton
);
801 target
->GetImages().FindGlobalVariables(ConstString(name
), UINT32_MAX
,
803 return variable_list
.GetSize() - old_size
;
806 void DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
807 Target
&target
= GetTarget();
808 StackFrame
*frame
= m_exe_ctx
.GetFramePtr();
810 // If no argument is present, issue an error message. There's no way to
812 if (command
.GetArgumentCount() <= 0) {
813 result
.AppendError("required argument missing; "
814 "specify your program variable to watch for");
818 // If no '-w' is specified, default to '-w modify'.
819 if (!m_option_watchpoint
.watch_type_specified
) {
820 m_option_watchpoint
.watch_type
= OptionGroupWatchpoint::eWatchModify
;
823 // We passed the sanity check for the command. Proceed to set the
825 lldb::addr_t addr
= 0;
829 ValueObjectSP valobj_sp
;
830 Stream
&output_stream
= result
.GetOutputStream();
832 // A simple watch variable gesture allows only one argument.
833 if (command
.GetArgumentCount() != 1) {
834 result
.AppendError("specify exactly one variable to watch for");
838 // Things have checked out ok...
840 uint32_t expr_path_options
=
841 StackFrame::eExpressionPathOptionCheckPtrVsMember
|
842 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess
;
843 valobj_sp
= frame
->GetValueForVariableExpressionPath(
844 command
.GetArgumentAtIndex(0), eNoDynamicValues
, expr_path_options
,
848 // Not in the frame; let's check the globals.
850 VariableList variable_list
;
851 ValueObjectList valobj_list
;
853 Status
error(Variable::GetValuesForVariableExpressionPath(
854 command
.GetArgumentAtIndex(0),
855 m_exe_ctx
.GetBestExecutionContextScope(), GetVariableCallback
,
856 &target
, variable_list
, valobj_list
));
858 if (valobj_list
.GetSize())
859 valobj_sp
= valobj_list
.GetValueObjectAtIndex(0);
862 CompilerType compiler_type
;
865 AddressType addr_type
;
866 addr
= valobj_sp
->GetAddressOf(false, &addr_type
);
867 if (addr_type
== eAddressTypeLoad
) {
868 // We're in business.
869 // Find out the size of this variable.
870 size
= m_option_watchpoint
.watch_size
.GetCurrentValue() == 0
871 ? valobj_sp
->GetByteSize().value_or(0)
872 : m_option_watchpoint
.watch_size
.GetCurrentValue();
874 compiler_type
= valobj_sp
->GetCompilerType();
876 const char *error_cstr
= error
.AsCString(nullptr);
878 result
.AppendError(error_cstr
);
880 result
.AppendErrorWithFormat("unable to find any variable "
881 "expression path that matches '%s'",
882 command
.GetArgumentAtIndex(0));
886 // Now it's time to create the watchpoint.
887 uint32_t watch_type
= 0;
888 switch (m_option_watchpoint
.watch_type
) {
889 case OptionGroupWatchpoint::eWatchModify
:
890 watch_type
|= LLDB_WATCH_TYPE_MODIFY
;
892 case OptionGroupWatchpoint::eWatchRead
:
893 watch_type
|= LLDB_WATCH_TYPE_READ
;
895 case OptionGroupWatchpoint::eWatchReadWrite
:
896 watch_type
|= LLDB_WATCH_TYPE_READ
| LLDB_WATCH_TYPE_WRITE
;
898 case OptionGroupWatchpoint::eWatchWrite
:
899 watch_type
|= LLDB_WATCH_TYPE_WRITE
;
901 case OptionGroupWatchpoint::eWatchInvalid
:
906 WatchpointSP watch_sp
=
907 target
.CreateWatchpoint(addr
, size
, &compiler_type
, watch_type
, error
);
909 result
.AppendErrorWithFormat(
910 "Watchpoint creation failed (addr=0x%" PRIx64
", size=%" PRIu64
911 ", variable expression='%s').\n",
912 addr
, static_cast<uint64_t>(size
), command
.GetArgumentAtIndex(0));
913 if (const char *error_message
= error
.AsCString(nullptr))
914 result
.AppendError(error_message
);
918 watch_sp
->SetWatchSpec(command
.GetArgumentAtIndex(0));
919 watch_sp
->SetWatchVariable(true);
921 if (var_sp
->GetDeclaration().GetFile()) {
923 // True to show fullpath for declaration file.
924 var_sp
->GetDeclaration().DumpStopContext(&ss
, true);
925 watch_sp
->SetDeclInfo(std::string(ss
.GetString()));
927 if (var_sp
->GetScope() == eValueTypeVariableLocal
)
928 watch_sp
->SetupVariableWatchpointDisabler(m_exe_ctx
.GetFrameSP());
930 output_stream
.Printf("Watchpoint created: ");
931 watch_sp
->GetDescription(&output_stream
, lldb::eDescriptionLevelFull
);
933 result
.SetStatus(eReturnStatusSuccessFinishResult
);
937 OptionGroupOptions m_option_group
;
938 OptionGroupWatchpoint m_option_watchpoint
;
941 // CommandObjectWatchpointSetExpression
944 class CommandObjectWatchpointSetExpression
: public CommandObjectRaw
{
946 CommandObjectWatchpointSetExpression(CommandInterpreter
&interpreter
)
948 interpreter
, "watchpoint set expression",
949 "Set a watchpoint on an address by supplying an expression. "
950 "Use the '-l' option to specify the language of the expression. "
951 "Use the '-w' option to specify the type of watchpoint and "
952 "the '-s' option to specify the byte size to watch for. "
953 "If no '-w' option is specified, it defaults to modify. "
954 "If no '-s' option is specified, it defaults to the target's "
955 "pointer byte size. "
956 "Note that there are limited hardware resources for watchpoints. "
957 "If watchpoint setting fails, consider disable/delete existing "
959 "to free up resources.",
961 eCommandRequiresFrame
| eCommandTryTargetAPILock
|
962 eCommandProcessMustBeLaunched
| eCommandProcessMustBePaused
) {
967 (lldb) watchpoint set expression -w modify -s 1 -- foo + 32
969 Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
971 AddSimpleArgumentList(eArgTypeExpression
);
973 // Absorb the '-w' and '-s' options into our option group.
974 m_option_group
.Append(&m_option_watchpoint
, LLDB_OPT_SET_ALL
,
976 m_option_group
.Finalize();
979 ~CommandObjectWatchpointSetExpression() override
= default;
981 // Overrides base class's behavior where WantsCompletion =
982 // !WantsRawCommandString.
983 bool WantsCompletion() override
{ return true; }
985 Options
*GetOptions() override
{ return &m_option_group
; }
988 void DoExecute(llvm::StringRef raw_command
,
989 CommandReturnObject
&result
) override
{
990 auto exe_ctx
= GetCommandInterpreter().GetExecutionContext();
991 m_option_group
.NotifyOptionParsingStarting(
992 &exe_ctx
); // This is a raw command, so notify the option group
994 Target
&target
= GetTarget();
995 StackFrame
*frame
= m_exe_ctx
.GetFramePtr();
997 OptionsWithRaw
args(raw_command
);
999 llvm::StringRef expr
= args
.GetRawPart();
1002 if (!ParseOptionsAndNotify(args
.GetArgs(), result
, m_option_group
,
1006 // If no argument is present, issue an error message. There's no way to
1007 // set a watchpoint.
1008 if (raw_command
.trim().empty()) {
1009 result
.AppendError("required argument missing; specify an expression "
1010 "to evaluate into the address to watch for");
1014 // If no '-w' is specified, default to '-w write'.
1015 if (!m_option_watchpoint
.watch_type_specified
) {
1016 m_option_watchpoint
.watch_type
= OptionGroupWatchpoint::eWatchModify
;
1019 // We passed the sanity check for the command. Proceed to set the
1021 lldb::addr_t addr
= 0;
1024 ValueObjectSP valobj_sp
;
1026 // Use expression evaluation to arrive at the address to watch.
1027 EvaluateExpressionOptions options
;
1028 options
.SetCoerceToId(false);
1029 options
.SetUnwindOnError(true);
1030 options
.SetKeepInMemory(false);
1031 options
.SetTryAllThreads(true);
1032 options
.SetTimeout(std::nullopt
);
1033 if (m_option_watchpoint
.language_type
!= eLanguageTypeUnknown
)
1034 options
.SetLanguage(m_option_watchpoint
.language_type
);
1036 ExpressionResults expr_result
=
1037 target
.EvaluateExpression(expr
, frame
, valobj_sp
, options
);
1038 if (expr_result
!= eExpressionCompleted
) {
1039 result
.AppendError("expression evaluation of address to watch failed");
1040 result
.AppendErrorWithFormat("expression evaluated: \n%s", expr
.data());
1041 if (valobj_sp
&& !valobj_sp
->GetError().Success())
1042 result
.AppendError(valobj_sp
->GetError().AsCString());
1046 // Get the address to watch.
1047 bool success
= false;
1048 addr
= valobj_sp
->GetValueAsUnsigned(0, &success
);
1050 result
.AppendError("expression did not evaluate to an address");
1054 if (m_option_watchpoint
.watch_size
.GetCurrentValue() != 0)
1055 size
= m_option_watchpoint
.watch_size
.GetCurrentValue();
1057 size
= target
.GetArchitecture().GetAddressByteSize();
1059 // Now it's time to create the watchpoint.
1060 uint32_t watch_type
;
1061 switch (m_option_watchpoint
.watch_type
) {
1062 case OptionGroupWatchpoint::eWatchRead
:
1063 watch_type
= LLDB_WATCH_TYPE_READ
;
1065 case OptionGroupWatchpoint::eWatchWrite
:
1066 watch_type
= LLDB_WATCH_TYPE_WRITE
;
1068 case OptionGroupWatchpoint::eWatchModify
:
1069 watch_type
= LLDB_WATCH_TYPE_MODIFY
;
1071 case OptionGroupWatchpoint::eWatchReadWrite
:
1072 watch_type
= LLDB_WATCH_TYPE_READ
| LLDB_WATCH_TYPE_WRITE
;
1075 watch_type
= LLDB_WATCH_TYPE_MODIFY
;
1078 // Fetch the type from the value object, the type of the watched object is
1080 /// of the expression, so convert to that if we found a valid type.
1081 CompilerType
compiler_type(valobj_sp
->GetCompilerType());
1083 std::optional
<uint64_t> valobj_size
= valobj_sp
->GetByteSize();
1084 // Set the type as a uint8_t array if the size being watched is
1085 // larger than the ValueObject's size (which is probably the size
1087 if (valobj_size
&& size
> *valobj_size
) {
1088 auto type_system
= compiler_type
.GetTypeSystem();
1090 CompilerType clang_uint8_type
=
1091 type_system
->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint
, 8);
1092 compiler_type
= clang_uint8_type
.GetArrayType(size
);
1097 WatchpointSP watch_sp
=
1098 target
.CreateWatchpoint(addr
, size
, &compiler_type
, watch_type
, error
);
1100 watch_sp
->SetWatchSpec(std::string(expr
));
1101 Stream
&output_stream
= result
.GetOutputStream();
1102 output_stream
.Printf("Watchpoint created: ");
1103 watch_sp
->GetDescription(&output_stream
, lldb::eDescriptionLevelFull
);
1104 output_stream
.EOL();
1105 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1107 result
.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
1108 ", size=%" PRIu64
").\n",
1109 addr
, (uint64_t)size
);
1110 if (error
.AsCString(nullptr))
1111 result
.AppendError(error
.AsCString());
1116 OptionGroupOptions m_option_group
;
1117 OptionGroupWatchpoint m_option_watchpoint
;
1120 // CommandObjectWatchpointSet
1123 class CommandObjectWatchpointSet
: public CommandObjectMultiword
{
1125 CommandObjectWatchpointSet(CommandInterpreter
&interpreter
)
1126 : CommandObjectMultiword(
1127 interpreter
, "watchpoint set", "Commands for setting a watchpoint.",
1128 "watchpoint set <subcommand> [<subcommand-options>]") {
1132 CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter
)));
1135 CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter
)));
1138 ~CommandObjectWatchpointSet() override
= default;
1141 // CommandObjectMultiwordWatchpoint
1142 #pragma mark MultiwordWatchpoint
1144 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(
1145 CommandInterpreter
&interpreter
)
1146 : CommandObjectMultiword(interpreter
, "watchpoint",
1147 "Commands for operating on watchpoints.",
1148 "watchpoint <subcommand> [<command-options>]") {
1149 CommandObjectSP
list_command_object(
1150 new CommandObjectWatchpointList(interpreter
));
1151 CommandObjectSP
enable_command_object(
1152 new CommandObjectWatchpointEnable(interpreter
));
1153 CommandObjectSP
disable_command_object(
1154 new CommandObjectWatchpointDisable(interpreter
));
1155 CommandObjectSP
delete_command_object(
1156 new CommandObjectWatchpointDelete(interpreter
));
1157 CommandObjectSP
ignore_command_object(
1158 new CommandObjectWatchpointIgnore(interpreter
));
1159 CommandObjectSP
command_command_object(
1160 new CommandObjectWatchpointCommand(interpreter
));
1161 CommandObjectSP
modify_command_object(
1162 new CommandObjectWatchpointModify(interpreter
));
1163 CommandObjectSP
set_command_object(
1164 new CommandObjectWatchpointSet(interpreter
));
1166 list_command_object
->SetCommandName("watchpoint list");
1167 enable_command_object
->SetCommandName("watchpoint enable");
1168 disable_command_object
->SetCommandName("watchpoint disable");
1169 delete_command_object
->SetCommandName("watchpoint delete");
1170 ignore_command_object
->SetCommandName("watchpoint ignore");
1171 command_command_object
->SetCommandName("watchpoint command");
1172 modify_command_object
->SetCommandName("watchpoint modify");
1173 set_command_object
->SetCommandName("watchpoint set");
1175 LoadSubCommand("list", list_command_object
);
1176 LoadSubCommand("enable", enable_command_object
);
1177 LoadSubCommand("disable", disable_command_object
);
1178 LoadSubCommand("delete", delete_command_object
);
1179 LoadSubCommand("ignore", ignore_command_object
);
1180 LoadSubCommand("command", command_command_object
);
1181 LoadSubCommand("modify", modify_command_object
);
1182 LoadSubCommand("set", set_command_object
);
1185 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default;