Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lldb / source / Commands / CommandObjectWatchpoint.cpp
blobcd1d226988f243e26618b3f3834c44e22ab0c03b
1 //===-- CommandObjectWatchpoint.cpp ---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectWatchpoint.h"
10 #include "CommandObjectWatchpointCommand.h"
12 #include <memory>
13 #include <vector>
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"
31 using namespace lldb;
32 using namespace lldb_private;
34 static void AddWatchpointDescription(Stream &s, Watchpoint &wp,
35 lldb::DescriptionLevel level) {
36 s.IndentMore();
37 wp.GetDescription(&s, level);
38 s.IndentLess();
39 s.EOL();
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.");
48 return false;
50 // Target passes our checks, return true.
51 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) {
60 uint32_t i;
61 for (i = 0; i < 4; ++i)
62 if (Arg.contains(RSA[i]))
63 return i;
64 return -1;
67 // Return true if wp_ids is successfully populated with the watch ids. False
68 // otherwise.
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)
74 return false;
75 WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
76 if (watch_sp) {
77 wp_ids.push_back(watch_sp->GetID());
78 return true;
79 } else
80 return false;
83 llvm::StringRef Minus("-");
84 std::vector<llvm::StringRef> StrRefArgs;
85 llvm::StringRef first;
86 llvm::StringRef second;
87 size_t i;
88 int32_t idx;
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());
94 continue;
96 // The Arg contains the range specifier, split it, then.
97 std::tie(first, second) = entry.ref().split(RSA[idx]);
98 if (!first.empty())
99 StrRefArgs.push_back(first);
100 StrRefArgs.push_back(Minus);
101 if (!second.empty())
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];
111 if (in_range) {
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))
115 return false;
116 // Found a range! Now append the elements.
117 for (id = beg; id <= end; ++id)
118 wp_ids.push_back(id);
119 in_range = false;
120 continue;
122 if (i < (size - 1) && StrRefArgs[i + 1] == Minus) {
123 if (Arg.getAsInteger(0, beg))
124 return false;
125 // Turn on the in_range flag, we are looking for end of range next.
126 ++i;
127 in_range = true;
128 continue;
130 // Otherwise, we have a simple ID. Just append it.
131 if (Arg.getAsInteger(0, beg))
132 return false;
133 wp_ids.push_back(beg);
136 // It is an error if after the loop, we're still in_range.
137 return !in_range;
140 // CommandObjectWatchpointList
142 // CommandObjectWatchpointList::Options
143 #pragma mark List::CommandOptions
144 #define LLDB_OPTIONS_watchpoint_list
145 #include "CommandOptions.inc"
147 #pragma mark List
149 class CommandObjectWatchpointList : public CommandObjectParsed {
150 public:
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
160 // arguments vector.
161 m_arguments.push_back(arg);
164 ~CommandObjectWatchpointList() override = default;
166 Options *GetOptions() override { return &m_options; }
168 class CommandOptions : public Options {
169 public:
170 CommandOptions() = default;
172 ~CommandOptions() override = default;
174 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
175 ExecutionContext *execution_context) override {
176 Status error;
177 const int short_option = m_getopt_table[option_idx].val;
179 switch (short_option) {
180 case 'b':
181 m_level = lldb::eDescriptionLevelBrief;
182 break;
183 case 'f':
184 m_level = lldb::eDescriptionLevelFull;
185 break;
186 case 'v':
187 m_level = lldb::eDescriptionLevelVerbose;
188 break;
189 default:
190 llvm_unreachable("Unimplemented option");
193 return error;
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;
209 protected:
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);
233 return;
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);
246 } else {
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.");
252 return;
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]);
258 if (watch_sp)
259 AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level);
260 result.SetStatus(eReturnStatusSuccessFinishNoResult);
265 private:
266 CommandOptions m_options;
269 // CommandObjectWatchpointEnable
270 #pragma mark Enable
272 class CommandObjectWatchpointEnable : public CommandObjectParsed {
273 public:
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
283 // arguments vector.
284 m_arguments.push_back(arg);
287 ~CommandObjectWatchpointEnable() override = default;
289 void
290 HandleArgumentCompletion(CompletionRequest &request,
291 OptionElementVector &opt_element_vector) override {
292 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
293 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
294 nullptr);
297 protected:
298 void DoExecute(Args &command, CommandReturnObject &result) override {
299 Target *target = &GetSelectedTarget();
300 if (!CheckTargetForWatchpointOperations(target, result))
301 return;
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.");
312 return;
315 if (command.GetArgumentCount() == 0) {
316 // No watchpoint selected; enable all currently set watchpoints.
317 target->EnableAllWatchpoints();
318 result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64
319 " watchpoints)\n",
320 (uint64_t)num_watchpoints);
321 result.SetStatus(eReturnStatusSuccessFinishNoResult);
322 } else {
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.");
328 return;
331 int count = 0;
332 const size_t size = wp_ids.size();
333 for (size_t i = 0; i < size; ++i)
334 if (target->EnableWatchpointByID(wp_ids[i]))
335 ++count;
336 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
337 result.SetStatus(eReturnStatusSuccessFinishNoResult);
342 // CommandObjectWatchpointDisable
343 #pragma mark Disable
345 class CommandObjectWatchpointDisable : public CommandObjectParsed {
346 public:
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
357 // arguments vector.
358 m_arguments.push_back(arg);
361 ~CommandObjectWatchpointDisable() override = default;
363 void
364 HandleArgumentCompletion(CompletionRequest &request,
365 OptionElementVector &opt_element_vector) override {
366 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
367 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
368 nullptr);
371 protected:
372 void DoExecute(Args &command, CommandReturnObject &result) override {
373 Target *target = &GetSelectedTarget();
374 if (!CheckTargetForWatchpointOperations(target, result))
375 return;
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.");
385 return;
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
392 " watchpoints)\n",
393 (uint64_t)num_watchpoints);
394 result.SetStatus(eReturnStatusSuccessFinishNoResult);
395 } else {
396 result.AppendError("Disable all watchpoints failed\n");
398 } else {
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.");
404 return;
407 int count = 0;
408 const size_t size = wp_ids.size();
409 for (size_t i = 0; i < size; ++i)
410 if (target->DisableWatchpointByID(wp_ids[i]))
411 ++count;
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
423 #pragma mark Delete
425 class CommandObjectWatchpointDelete : public CommandObjectParsed {
426 public:
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
436 // arguments vector.
437 m_arguments.push_back(arg);
440 ~CommandObjectWatchpointDelete() override = default;
442 void
443 HandleArgumentCompletion(CompletionRequest &request,
444 OptionElementVector &opt_element_vector) override {
445 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
446 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
447 nullptr);
450 Options *GetOptions() override { return &m_options; }
452 class CommandOptions : public Options {
453 public:
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) {
463 case 'f':
464 m_force = true;
465 break;
466 default:
467 llvm_unreachable("Unimplemented option");
470 return {};
473 void OptionParsingStarting(ExecutionContext *execution_context) override {
474 m_force = false;
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;
485 protected:
486 void DoExecute(Args &command, CommandReturnObject &result) override {
487 Target *target = &GetSelectedTarget();
488 if (!CheckTargetForWatchpointOperations(target, result))
489 return;
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.");
500 return;
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?",
507 true)) {
508 result.AppendMessage("Operation cancelled...");
509 } else {
510 target->RemoveAllWatchpoints();
511 result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
512 " watchpoints)\n",
513 (uint64_t)num_watchpoints);
515 result.SetStatus(eReturnStatusSuccessFinishNoResult);
516 return;
519 // Particular watchpoints selected; delete them.
520 std::vector<uint32_t> wp_ids;
521 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command,
522 wp_ids)) {
523 result.AppendError("Invalid watchpoints specification.");
524 return;
527 int count = 0;
528 const size_t size = wp_ids.size();
529 for (size_t i = 0; i < size; ++i)
530 if (target->RemoveWatchpointByID(wp_ids[i]))
531 ++count;
532 result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
533 result.SetStatus(eReturnStatusSuccessFinishNoResult);
536 private:
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 {
547 public:
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
557 // arguments vector.
558 m_arguments.push_back(arg);
561 ~CommandObjectWatchpointIgnore() override = default;
563 void
564 HandleArgumentCompletion(CompletionRequest &request,
565 OptionElementVector &opt_element_vector) override {
566 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
567 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
568 nullptr);
571 Options *GetOptions() override { return &m_options; }
573 class CommandOptions : public Options {
574 public:
575 CommandOptions() = default;
577 ~CommandOptions() override = default;
579 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
580 ExecutionContext *execution_context) override {
581 Status error;
582 const int short_option = m_getopt_table[option_idx].val;
584 switch (short_option) {
585 case 'i':
586 if (option_arg.getAsInteger(0, m_ignore_count))
587 error.SetErrorStringWithFormat("invalid ignore count '%s'",
588 option_arg.str().c_str());
589 break;
590 default:
591 llvm_unreachable("Unimplemented option");
594 return error;
597 void OptionParsingStarting(ExecutionContext *execution_context) override {
598 m_ignore_count = 0;
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;
610 protected:
611 void DoExecute(Args &command, CommandReturnObject &result) override {
612 Target *target = &GetSelectedTarget();
613 if (!CheckTargetForWatchpointOperations(target, result))
614 return;
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.");
625 return;
628 if (command.GetArgumentCount() == 0) {
629 target->IgnoreAllWatchpoints(m_options.m_ignore_count);
630 result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
631 " watchpoints)\n",
632 (uint64_t)num_watchpoints);
633 result.SetStatus(eReturnStatusSuccessFinishNoResult);
634 } else {
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.");
640 return;
643 int count = 0;
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))
647 ++count;
648 result.AppendMessageWithFormat("%d watchpoints ignored.\n", count);
649 result.SetStatus(eReturnStatusSuccessFinishNoResult);
653 private:
654 CommandOptions m_options;
657 // CommandObjectWatchpointModify
659 #pragma mark Modify::CommandOptions
660 #define LLDB_OPTIONS_watchpoint_modify
661 #include "CommandOptions.inc"
663 #pragma mark Modify
665 class CommandObjectWatchpointModify : public CommandObjectParsed {
666 public:
667 CommandObjectWatchpointModify(CommandInterpreter &interpreter)
668 : CommandObjectParsed(
669 interpreter, "watchpoint modify",
670 "Modify the options on a watchpoint or set of watchpoints in the "
671 "executable. "
672 "If no watchpoint is specified, act on the last created "
673 "watchpoint. "
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
680 // arguments vector.
681 m_arguments.push_back(arg);
684 ~CommandObjectWatchpointModify() override = default;
686 void
687 HandleArgumentCompletion(CompletionRequest &request,
688 OptionElementVector &opt_element_vector) override {
689 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
690 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request,
691 nullptr);
694 Options *GetOptions() override { return &m_options; }
696 class CommandOptions : public Options {
697 public:
698 CommandOptions() = default;
700 ~CommandOptions() override = default;
702 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
703 ExecutionContext *execution_context) override {
704 Status error;
705 const int short_option = m_getopt_table[option_idx].val;
707 switch (short_option) {
708 case 'c':
709 m_condition = std::string(option_arg);
710 m_condition_passed = true;
711 break;
712 default:
713 llvm_unreachable("Unimplemented option");
716 return error;
719 void OptionParsingStarting(ExecutionContext *execution_context) override {
720 m_condition.clear();
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;
734 protected:
735 void DoExecute(Args &command, CommandReturnObject &result) override {
736 Target *target = &GetSelectedTarget();
737 if (!CheckTargetForWatchpointOperations(target, result))
738 return;
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.");
749 return;
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);
756 } else {
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.");
762 return;
765 int count = 0;
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]);
769 if (watch_sp) {
770 watch_sp->SetCondition(m_options.m_condition.c_str());
771 ++count;
774 result.AppendMessageWithFormat("%d watchpoints modified.\n", count);
775 result.SetStatus(eReturnStatusSuccessFinishNoResult);
779 private:
780 CommandOptions m_options;
783 // CommandObjectWatchpointSetVariable
784 #pragma mark SetVariable
786 class CommandObjectWatchpointSetVariable : public CommandObjectParsed {
787 public:
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 "
796 "byte size. "
797 "Note that there are limited hardware resources for watchpoints. "
798 "If watchpoint setting fails, consider disable/delete existing "
799 "ones "
800 "to free up resources.",
801 nullptr,
802 eCommandRequiresFrame | eCommandTryTargetAPILock |
803 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
804 SetHelpLong(
806 Examples:
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;
834 void
835 HandleArgumentCompletion(CompletionRequest &request,
836 OptionElementVector &opt_element_vector) override {
837 if (request.GetCursorIndex() != 0)
838 return;
839 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
840 GetCommandInterpreter(), lldb::eVariablePathCompletion, request,
841 nullptr);
844 Options *GetOptions() override { return &m_option_group; }
846 protected:
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);
851 if (target)
852 target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX,
853 variable_list);
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
862 // set a watchpoint.
863 if (command.GetArgumentCount() <= 0) {
864 result.AppendError("required argument missing; "
865 "specify your program variable to watch for");
866 return;
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
875 // watchpoint now.
876 lldb::addr_t addr = 0;
877 size_t size = 0;
879 VariableSP var_sp;
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");
886 return;
889 // Things have checked out ok...
890 Status error;
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,
896 var_sp, error);
898 if (!valobj_sp) {
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;
915 if (valobj_sp) {
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();
926 } else {
927 const char *error_cstr = error.AsCString(nullptr);
928 if (error_cstr)
929 result.AppendError(error_cstr);
930 else
931 result.AppendErrorWithFormat("unable to find any variable "
932 "expression path that matches '%s'",
933 command.GetArgumentAtIndex(0));
934 return;
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;
942 break;
943 case OptionGroupWatchpoint::eWatchRead:
944 watch_type |= LLDB_WATCH_TYPE_READ;
945 break;
946 case OptionGroupWatchpoint::eWatchReadWrite:
947 watch_type |= LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE;
948 break;
949 case OptionGroupWatchpoint::eWatchWrite:
950 watch_type |= LLDB_WATCH_TYPE_WRITE;
951 break;
952 case OptionGroupWatchpoint::eWatchInvalid:
953 break;
956 error.Clear();
957 WatchpointSP watch_sp =
958 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error);
959 if (!watch_sp) {
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);
966 return;
969 watch_sp->SetWatchSpec(command.GetArgumentAtIndex(0));
970 watch_sp->SetWatchVariable(true);
971 if (var_sp) {
972 if (var_sp->GetDeclaration().GetFile()) {
973 StreamString ss;
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);
983 output_stream.EOL();
984 result.SetStatus(eReturnStatusSuccessFinishResult);
987 private:
988 OptionGroupOptions m_option_group;
989 OptionGroupWatchpoint m_option_watchpoint;
992 // CommandObjectWatchpointSetExpression
993 #pragma mark Set
995 class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
996 public:
997 CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter)
998 : CommandObjectRaw(
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 "
1009 "ones "
1010 "to free up resources.",
1012 eCommandRequiresFrame | eCommandTryTargetAPILock |
1013 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
1014 SetHelpLong(
1016 Examples:
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,
1037 LLDB_OPT_SET_1);
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; }
1049 protected:
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();
1063 if (args.HasArgs())
1064 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
1065 exe_ctx))
1066 return;
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");
1073 return;
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
1082 // watchpoint now.
1083 lldb::addr_t addr = 0;
1084 size_t size = 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());
1105 return;
1108 // Get the address to watch.
1109 bool success = false;
1110 addr = valobj_sp->GetValueAsUnsigned(0, &success);
1111 if (!success) {
1112 result.AppendError("expression did not evaluate to an address");
1113 return;
1116 if (m_option_watchpoint.watch_size != 0)
1117 size = m_option_watchpoint.watch_size;
1118 else
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;
1126 break;
1127 case OptionGroupWatchpoint::eWatchWrite:
1128 watch_type = LLDB_WATCH_TYPE_WRITE;
1129 break;
1130 case OptionGroupWatchpoint::eWatchModify:
1131 watch_type = LLDB_WATCH_TYPE_MODIFY;
1132 break;
1133 case OptionGroupWatchpoint::eWatchReadWrite:
1134 watch_type = LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE;
1135 break;
1136 default:
1137 watch_type = LLDB_WATCH_TYPE_MODIFY;
1140 // Fetch the type from the value object, the type of the watched object is
1141 // the pointee type
1142 /// of the expression, so convert to that if we found a valid type.
1143 CompilerType compiler_type(valobj_sp->GetCompilerType());
1145 Status error;
1146 WatchpointSP watch_sp =
1147 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error);
1148 if (watch_sp) {
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);
1155 } else {
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());
1164 private:
1165 OptionGroupOptions m_option_group;
1166 OptionGroupWatchpoint m_option_watchpoint;
1169 // CommandObjectWatchpointSet
1170 #pragma mark Set
1172 class CommandObjectWatchpointSet : public CommandObjectMultiword {
1173 public:
1174 CommandObjectWatchpointSet(CommandInterpreter &interpreter)
1175 : CommandObjectMultiword(
1176 interpreter, "watchpoint set", "Commands for setting a watchpoint.",
1177 "watchpoint set <subcommand> [<subcommand-options>]") {
1179 LoadSubCommand(
1180 "variable",
1181 CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter)));
1182 LoadSubCommand(
1183 "expression",
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;