LLDB mainline
CommandObjectWatchpoint.cpp
Go to the documentation of this file.
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//===----------------------------------------------------------------------===//
8
11
12#include <vector>
13
14#include "llvm/ADT/StringRef.h"
15
26#include "lldb/Target/Target.h"
28
29using namespace lldb;
30using namespace lldb_private;
31
34 s.IndentMore();
35 wp.GetDescription(&s, level);
36 s.IndentLess();
37 s.EOL();
38}
39
41 CommandReturnObject &result) {
42 bool process_is_valid =
43 target->GetProcessSP() && target->GetProcessSP()->IsAlive();
44 if (!process_is_valid) {
45 result.AppendError("There's no process or it is not alive.");
46 return false;
47 }
48 // Target passes our checks, return true.
49 return true;
50}
51
52// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
53static const char *RSA[4] = {"-", "to", "To", "TO"};
54
55// Return the index to RSA if found; otherwise -1 is returned.
56static int32_t WithRSAIndex(llvm::StringRef Arg) {
57
58 uint32_t i;
59 for (i = 0; i < 4; ++i)
60 if (Arg.contains(RSA[i]))
61 return i;
62 return -1;
63}
64
65// Return true if wp_ids is successfully populated with the watch ids. False
66// otherwise.
68 Target *target, Args &args, std::vector<uint32_t> &wp_ids) {
69 // Pre-condition: args.GetArgumentCount() > 0.
70 if (args.GetArgumentCount() == 0) {
71 if (target == nullptr)
72 return false;
73 WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
74 if (watch_sp) {
75 wp_ids.push_back(watch_sp->GetID());
76 return true;
77 } else
78 return false;
79 }
80
81 llvm::StringRef Minus("-");
82 std::vector<llvm::StringRef> StrRefArgs;
83 llvm::StringRef first;
84 llvm::StringRef second;
85 size_t i;
86 int32_t idx;
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());
92 continue;
93 }
94 // The Arg contains the range specifier, split it, then.
95 std::tie(first, second) = entry.ref().split(RSA[idx]);
96 if (!first.empty())
97 StrRefArgs.push_back(first);
98 StrRefArgs.push_back(Minus);
99 if (!second.empty())
100 StrRefArgs.push_back(second);
101 }
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];
109 if (in_range) {
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))
113 return false;
114 // Found a range! Now append the elements.
115 for (id = beg; id <= end; ++id)
116 wp_ids.push_back(id);
117 in_range = false;
118 continue;
119 }
120 if (i < (size - 1) && StrRefArgs[i + 1] == Minus) {
121 if (Arg.getAsInteger(0, beg))
122 return false;
123 // Turn on the in_range flag, we are looking for end of range next.
124 ++i;
125 in_range = true;
126 continue;
127 }
128 // Otherwise, we have a simple ID. Just append it.
129 if (Arg.getAsInteger(0, beg))
130 return false;
131 wp_ids.push_back(beg);
132 }
133
134 // It is an error if after the loop, we're still in_range.
135 return !in_range;
136}
137
138// CommandObjectWatchpointList
139
140// CommandObjectWatchpointList::Options
141#pragma mark List::CommandOptions
142#define LLDB_OPTIONS_watchpoint_list
143#include "CommandOptions.inc"
144
145#pragma mark List
146
148public:
151 interpreter, "watchpoint list",
152 "List all watchpoints at configurable levels of detail.", nullptr,
153 eCommandRequiresTarget) {
157 // Add the entry for the first argument for this command to the object's
158 // arguments vector.
159 m_arguments.push_back(arg);
160 }
161
162 ~CommandObjectWatchpointList() override = default;
163
164 Options *GetOptions() override { return &m_options; }
165
166 class CommandOptions : public Options {
167 public:
168 CommandOptions() = default;
169
170 ~CommandOptions() override = default;
171
172 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
173 ExecutionContext *execution_context) override {
175 const int short_option = m_getopt_table[option_idx].val;
176
177 switch (short_option) {
178 case 'b':
180 break;
181 case 'f':
183 break;
184 case 'v':
186 break;
187 default:
188 llvm_unreachable("Unimplemented option");
189 }
190
191 return error;
192 }
193
194 void OptionParsingStarting(ExecutionContext *execution_context) override {
196 }
197
198 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
199 return llvm::ArrayRef(g_watchpoint_list_options);
200 }
201
202 // Instance variables to hold the values for command options.
203
205 };
206
207protected:
208 bool DoExecute(Args &command, CommandReturnObject &result) override {
209 Target *target = &GetSelectedTarget();
210
211 if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) {
212 std::optional<uint32_t> num_supported_hardware_watchpoints =
213 target->GetProcessSP()->GetWatchpointSlotCount();
214
215 if (num_supported_hardware_watchpoints)
217 "Number of supported hardware watchpoints: %u\n",
218 *num_supported_hardware_watchpoints);
219 }
220
221 const WatchpointList &watchpoints = target->GetWatchpointList();
222
223 std::unique_lock<std::recursive_mutex> lock;
224 target->GetWatchpointList().GetListMutex(lock);
225
226 size_t num_watchpoints = watchpoints.GetSize();
227
228 if (num_watchpoints == 0) {
229 result.AppendMessage("No watchpoints currently set.");
231 return true;
232 }
233
234 Stream &output_stream = result.GetOutputStream();
235
236 if (command.GetArgumentCount() == 0) {
237 // No watchpoint selected; show info about all currently set watchpoints.
238 result.AppendMessage("Current watchpoints:");
239 for (size_t i = 0; i < num_watchpoints; ++i) {
240 WatchpointSP watch_sp = watchpoints.GetByIndex(i);
241 AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level);
242 }
244 } else {
245 // Particular watchpoints selected; enable them.
246 std::vector<uint32_t> wp_ids;
248 target, command, wp_ids)) {
249 result.AppendError("Invalid watchpoints specification.");
250 return false;
251 }
252
253 const size_t size = wp_ids.size();
254 for (size_t i = 0; i < size; ++i) {
255 WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]);
256 if (watch_sp)
257 AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level);
259 }
260 }
261
262 return result.Succeeded();
263 }
264
265private:
267};
268
269// CommandObjectWatchpointEnable
270#pragma mark Enable
271
273public:
275 : CommandObjectParsed(interpreter, "enable",
276 "Enable the specified disabled watchpoint(s). If "
277 "no watchpoints are specified, enable all of them.",
278 nullptr, eCommandRequiresTarget) {
282 // Add the entry for the first argument for this command to the object's
283 // arguments vector.
284 m_arguments.push_back(arg);
285 }
286
287 ~CommandObjectWatchpointEnable() override = default;
288
289 void
291 OptionElementVector &opt_element_vector) override {
293 GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion,
294 request, nullptr);
295 }
296
297protected:
298 bool DoExecute(Args &command, CommandReturnObject &result) override {
299 Target *target = &GetSelectedTarget();
300 if (!CheckTargetForWatchpointOperations(target, result))
301 return false;
302
303 std::unique_lock<std::recursive_mutex> lock;
304 target->GetWatchpointList().GetListMutex(lock);
305
306 const WatchpointList &watchpoints = target->GetWatchpointList();
307
308 size_t num_watchpoints = watchpoints.GetSize();
309
310 if (num_watchpoints == 0) {
311 result.AppendError("No watchpoints exist to be enabled.");
312 return false;
313 }
314
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);
322 } else {
323 // Particular watchpoints selected; enable them.
324 std::vector<uint32_t> wp_ids;
326 target, command, wp_ids)) {
327 result.AppendError("Invalid watchpoints specification.");
328 return false;
329 }
330
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);
338 }
339
340 return result.Succeeded();
341 }
342};
343
344// CommandObjectWatchpointDisable
345#pragma mark Disable
346
348public:
350 : CommandObjectParsed(interpreter, "watchpoint disable",
351 "Disable the specified watchpoint(s) without "
352 "removing it/them. If no watchpoints are "
353 "specified, disable them all.",
354 nullptr, eCommandRequiresTarget) {
358 // Add the entry for the first argument for this command to the object's
359 // arguments vector.
360 m_arguments.push_back(arg);
361 }
362
364
365 void
367 OptionElementVector &opt_element_vector) override {
369 GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion,
370 request, nullptr);
371 }
372
373protected:
374 bool DoExecute(Args &command, CommandReturnObject &result) override {
375 Target *target = &GetSelectedTarget();
376 if (!CheckTargetForWatchpointOperations(target, result))
377 return false;
378
379 std::unique_lock<std::recursive_mutex> lock;
380 target->GetWatchpointList().GetListMutex(lock);
381
382 const WatchpointList &watchpoints = target->GetWatchpointList();
383 size_t num_watchpoints = watchpoints.GetSize();
384
385 if (num_watchpoints == 0) {
386 result.AppendError("No watchpoints exist to be disabled.");
387 return false;
388 }
389
390 if (command.GetArgumentCount() == 0) {
391 // No watchpoint selected; disable all currently set watchpoints.
392 if (target->DisableAllWatchpoints()) {
393 result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64
394 " watchpoints)\n",
395 (uint64_t)num_watchpoints);
397 } else {
398 result.AppendError("Disable all watchpoints failed\n");
399 }
400 } else {
401 // Particular watchpoints selected; disable them.
402 std::vector<uint32_t> wp_ids;
404 target, command, wp_ids)) {
405 result.AppendError("Invalid watchpoints specification.");
406 return false;
407 }
408
409 int count = 0;
410 const size_t size = wp_ids.size();
411 for (size_t i = 0; i < size; ++i)
412 if (target->DisableWatchpointByID(wp_ids[i]))
413 ++count;
414 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
416 }
417
418 return result.Succeeded();
419 }
420};
421
422// CommandObjectWatchpointDelete
423#define LLDB_OPTIONS_watchpoint_delete
424#include "CommandOptions.inc"
425
426// CommandObjectWatchpointDelete
427#pragma mark Delete
428
430public:
432 : CommandObjectParsed(interpreter, "watchpoint delete",
433 "Delete the specified watchpoint(s). If no "
434 "watchpoints are specified, delete them all.",
435 nullptr, eCommandRequiresTarget) {
439 // Add the entry for the first argument for this command to the object's
440 // arguments vector.
441 m_arguments.push_back(arg);
442 }
443
444 ~CommandObjectWatchpointDelete() override = default;
445
446 void
448 OptionElementVector &opt_element_vector) override {
450 GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion,
451 request, nullptr);
452 }
453
454 Options *GetOptions() override { return &m_options; }
455
456 class CommandOptions : public Options {
457 public:
458 CommandOptions() = default;
459
460 ~CommandOptions() override = default;
461
462 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
463 ExecutionContext *execution_context) override {
464 const int short_option = m_getopt_table[option_idx].val;
465
466 switch (short_option) {
467 case 'f':
468 m_force = true;
469 break;
470 default:
471 llvm_unreachable("Unimplemented option");
472 }
473
474 return {};
475 }
476
477 void OptionParsingStarting(ExecutionContext *execution_context) override {
478 m_force = false;
479 }
480
481 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
482 return llvm::ArrayRef(g_watchpoint_delete_options);
483 }
484
485 // Instance variables to hold the values for command options.
486 bool m_force = false;
487 };
488
489protected:
490 bool DoExecute(Args &command, CommandReturnObject &result) override {
491 Target *target = &GetSelectedTarget();
492 if (!CheckTargetForWatchpointOperations(target, result))
493 return false;
494
495 std::unique_lock<std::recursive_mutex> lock;
496 target->GetWatchpointList().GetListMutex(lock);
497
498 const WatchpointList &watchpoints = target->GetWatchpointList();
499
500 size_t num_watchpoints = watchpoints.GetSize();
501
502 if (num_watchpoints == 0) {
503 result.AppendError("No watchpoints exist to be deleted.");
504 return false;
505 }
506
507 if (command.empty()) {
508 if (!m_options.m_force &&
509 !m_interpreter.Confirm(
510 "About to delete all watchpoints, do you want to do that?",
511 true)) {
512 result.AppendMessage("Operation cancelled...");
513 } else {
514 target->RemoveAllWatchpoints();
515 result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
516 " watchpoints)\n",
517 (uint64_t)num_watchpoints);
518 }
520 return result.Succeeded();
521 }
522
523 // Particular watchpoints selected; delete them.
524 std::vector<uint32_t> wp_ids;
526 wp_ids)) {
527 result.AppendError("Invalid watchpoints specification.");
528 return false;
529 }
530
531 int count = 0;
532 const size_t size = wp_ids.size();
533 for (size_t i = 0; i < size; ++i)
534 if (target->RemoveWatchpointByID(wp_ids[i]))
535 ++count;
536 result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
538
539 return result.Succeeded();
540 }
541
542private:
544};
545
546// CommandObjectWatchpointIgnore
547
548#pragma mark Ignore::CommandOptions
549#define LLDB_OPTIONS_watchpoint_ignore
550#include "CommandOptions.inc"
551
553public:
555 : CommandObjectParsed(interpreter, "watchpoint ignore",
556 "Set ignore count on the specified watchpoint(s). "
557 "If no watchpoints are specified, set them all.",
558 nullptr, eCommandRequiresTarget) {
562 // Add the entry for the first argument for this command to the object's
563 // arguments vector.
564 m_arguments.push_back(arg);
565 }
566
567 ~CommandObjectWatchpointIgnore() override = default;
568
569 void
571 OptionElementVector &opt_element_vector) override {
573 GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion,
574 request, nullptr);
575 }
576
577 Options *GetOptions() override { return &m_options; }
578
579 class CommandOptions : public Options {
580 public:
581 CommandOptions() = default;
582
583 ~CommandOptions() override = default;
584
585 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
586 ExecutionContext *execution_context) override {
588 const int short_option = m_getopt_table[option_idx].val;
589
590 switch (short_option) {
591 case 'i':
592 if (option_arg.getAsInteger(0, m_ignore_count))
593 error.SetErrorStringWithFormat("invalid ignore count '%s'",
594 option_arg.str().c_str());
595 break;
596 default:
597 llvm_unreachable("Unimplemented option");
598 }
599
600 return error;
601 }
602
603 void OptionParsingStarting(ExecutionContext *execution_context) override {
604 m_ignore_count = 0;
605 }
606
607 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
608 return llvm::ArrayRef(g_watchpoint_ignore_options);
609 }
610
611 // Instance variables to hold the values for command options.
612
613 uint32_t m_ignore_count = 0;
614 };
615
616protected:
617 bool DoExecute(Args &command, CommandReturnObject &result) override {
618 Target *target = &GetSelectedTarget();
619 if (!CheckTargetForWatchpointOperations(target, result))
620 return false;
621
622 std::unique_lock<std::recursive_mutex> lock;
623 target->GetWatchpointList().GetListMutex(lock);
624
625 const WatchpointList &watchpoints = target->GetWatchpointList();
626
627 size_t num_watchpoints = watchpoints.GetSize();
628
629 if (num_watchpoints == 0) {
630 result.AppendError("No watchpoints exist to be ignored.");
631 return false;
632 }
633
634 if (command.GetArgumentCount() == 0) {
635 target->IgnoreAllWatchpoints(m_options.m_ignore_count);
636 result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
637 " watchpoints)\n",
638 (uint64_t)num_watchpoints);
640 } else {
641 // Particular watchpoints selected; ignore them.
642 std::vector<uint32_t> wp_ids;
644 target, command, wp_ids)) {
645 result.AppendError("Invalid watchpoints specification.");
646 return false;
647 }
648
649 int count = 0;
650 const size_t size = wp_ids.size();
651 for (size_t i = 0; i < size; ++i)
652 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
653 ++count;
654 result.AppendMessageWithFormat("%d watchpoints ignored.\n", count);
656 }
657
658 return result.Succeeded();
659 }
660
661private:
663};
664
665// CommandObjectWatchpointModify
666
667#pragma mark Modify::CommandOptions
668#define LLDB_OPTIONS_watchpoint_modify
669#include "CommandOptions.inc"
670
671#pragma mark Modify
672
674public:
677 interpreter, "watchpoint modify",
678 "Modify the options on a watchpoint or set of watchpoints in the "
679 "executable. "
680 "If no watchpoint is specified, act on the last created "
681 "watchpoint. "
682 "Passing an empty argument clears the modification.",
683 nullptr, eCommandRequiresTarget) {
687 // Add the entry for the first argument for this command to the object's
688 // arguments vector.
689 m_arguments.push_back(arg);
690 }
691
692 ~CommandObjectWatchpointModify() override = default;
693
694 void
696 OptionElementVector &opt_element_vector) override {
698 GetCommandInterpreter(), CommandCompletions::eWatchPointIDCompletion,
699 request, nullptr);
700 }
701
702 Options *GetOptions() override { return &m_options; }
703
704 class CommandOptions : public Options {
705 public:
706 CommandOptions() = default;
707
708 ~CommandOptions() override = default;
709
710 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
711 ExecutionContext *execution_context) override {
713 const int short_option = m_getopt_table[option_idx].val;
714
715 switch (short_option) {
716 case 'c':
717 m_condition = std::string(option_arg);
718 m_condition_passed = true;
719 break;
720 default:
721 llvm_unreachable("Unimplemented option");
722 }
723
724 return error;
725 }
726
727 void OptionParsingStarting(ExecutionContext *execution_context) override {
728 m_condition.clear();
729 m_condition_passed = false;
730 }
731
732 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
733 return llvm::ArrayRef(g_watchpoint_modify_options);
734 }
735
736 // Instance variables to hold the values for command options.
737
738 std::string m_condition;
739 bool m_condition_passed = false;
740 };
741
742protected:
743 bool DoExecute(Args &command, CommandReturnObject &result) override {
744 Target *target = &GetSelectedTarget();
745 if (!CheckTargetForWatchpointOperations(target, result))
746 return false;
747
748 std::unique_lock<std::recursive_mutex> lock;
749 target->GetWatchpointList().GetListMutex(lock);
750
751 const WatchpointList &watchpoints = target->GetWatchpointList();
752
753 size_t num_watchpoints = watchpoints.GetSize();
754
755 if (num_watchpoints == 0) {
756 result.AppendError("No watchpoints exist to be modified.");
757 return false;
758 }
759
760 if (command.GetArgumentCount() == 0) {
761 WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
762 watch_sp->SetCondition(m_options.m_condition.c_str());
764 } else {
765 // Particular watchpoints selected; set condition on them.
766 std::vector<uint32_t> wp_ids;
768 target, command, wp_ids)) {
769 result.AppendError("Invalid watchpoints specification.");
770 return false;
771 }
772
773 int count = 0;
774 const size_t size = wp_ids.size();
775 for (size_t i = 0; i < size; ++i) {
776 WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]);
777 if (watch_sp) {
778 watch_sp->SetCondition(m_options.m_condition.c_str());
779 ++count;
780 }
781 }
782 result.AppendMessageWithFormat("%d watchpoints modified.\n", count);
784 }
785
786 return result.Succeeded();
787 }
788
789private:
791};
792
793// CommandObjectWatchpointSetVariable
794#pragma mark SetVariable
795
797public:
800 interpreter, "watchpoint set variable",
801 "Set a watchpoint on a variable. "
802 "Use the '-w' option to specify the type of watchpoint and "
803 "the '-s' option to specify the byte size to watch for. "
804 "If no '-w' option is specified, it defaults to write. "
805 "If no '-s' option is specified, it defaults to the variable's "
806 "byte size. "
807 "Note that there are limited hardware resources for watchpoints. "
808 "If watchpoint setting fails, consider disable/delete existing "
809 "ones "
810 "to free up resources.",
811 nullptr,
812 eCommandRequiresFrame | eCommandTryTargetAPILock |
813 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
814 SetHelpLong(
815 R"(
816Examples:
817
818(lldb) watchpoint set variable -w read_write my_global_var
819
820)"
821 " Watches my_global_var for read/write access, with the region to watch \
822corresponding to the byte size of the data type.");
823
825 CommandArgumentData var_name_arg;
826
827 // Define the only variant of this arg.
828 var_name_arg.arg_type = eArgTypeVarName;
829 var_name_arg.arg_repetition = eArgRepeatPlain;
830
831 // Push the variant into the argument entry.
832 arg.push_back(var_name_arg);
833
834 // Push the data for the only argument into the m_arguments vector.
835 m_arguments.push_back(arg);
836
837 // Absorb the '-w' and '-s' options into our option group.
838 m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
840 m_option_group.Finalize();
842
843 ~CommandObjectWatchpointSetVariable() override = default;
844
845 void
846 HandleArgumentCompletion(CompletionRequest &request,
847 OptionElementVector &opt_element_vector) override {
848 if (request.GetCursorIndex() != 0)
849 return;
851 GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
852 request, nullptr);
854
855 Options *GetOptions() override { return &m_option_group; }
856
857protected:
858 static size_t GetVariableCallback(void *baton, const char *name,
859 VariableList &variable_list) {
860 size_t old_size = variable_list.GetSize();
861 Target *target = static_cast<Target *>(baton);
862 if (target)
864 variable_list);
865 return variable_list.GetSize() - old_size;
866 }
867
868 bool DoExecute(Args &command, CommandReturnObject &result) override {
869 Target *target = GetDebugger().GetSelectedTarget().get();
870 StackFrame *frame = m_exe_ctx.GetFramePtr();
871
872 // If no argument is present, issue an error message. There's no way to
873 // set a watchpoint.
874 if (command.GetArgumentCount() <= 0) {
875 result.AppendError("required argument missing; "
876 "specify your program variable to watch for");
877 return false;
878 }
879
880 // If no '-w' is specified, default to '-w write'.
881 if (!m_option_watchpoint.watch_type_specified) {
882 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
883 }
884
885 // We passed the sanity check for the command. Proceed to set the
886 // watchpoint now.
887 lldb::addr_t addr = 0;
888 size_t size = 0;
889
890 VariableSP var_sp;
891 ValueObjectSP valobj_sp;
892 Stream &output_stream = result.GetOutputStream();
893
894 // A simple watch variable gesture allows only one argument.
895 if (command.GetArgumentCount() != 1) {
896 result.AppendError("specify exactly one variable to watch for");
897 return false;
898 }
899
900 // Things have checked out ok...
902 uint32_t expr_path_options =
905 valobj_sp = frame->GetValueForVariableExpressionPath(
906 command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
907 var_sp, error);
908
909 if (!valobj_sp) {
910 // Not in the frame; let's check the globals.
911
912 VariableList variable_list;
913 ValueObjectList valobj_list;
914
916 command.GetArgumentAtIndex(0),
917 m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target,
918 variable_list, valobj_list));
919
920 if (valobj_list.GetSize())
921 valobj_sp = valobj_list.GetValueObjectAtIndex(0);
922 }
923
924 CompilerType compiler_type;
925
926 if (valobj_sp) {
927 AddressType addr_type;
928 addr = valobj_sp->GetAddressOf(false, &addr_type);
929 if (addr_type == eAddressTypeLoad) {
930 // We're in business.
931 // Find out the size of this variable.
932 size = m_option_watchpoint.watch_size == 0
933 ? valobj_sp->GetByteSize().value_or(0)
934 : m_option_watchpoint.watch_size;
935 }
936 compiler_type = valobj_sp->GetCompilerType();
937 } else {
938 const char *error_cstr = error.AsCString(nullptr);
939 if (error_cstr)
940 result.AppendError(error_cstr);
941 else
942 result.AppendErrorWithFormat("unable to find any variable "
943 "expression path that matches '%s'",
944 command.GetArgumentAtIndex(0));
945 return false;
946 }
947
948 // Now it's time to create the watchpoint.
949 uint32_t watch_type = m_option_watchpoint.watch_type;
950
951 error.Clear();
952 WatchpointSP watch_sp =
953 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error);
954 if (watch_sp) {
955 watch_sp->SetWatchSpec(command.GetArgumentAtIndex(0));
956 watch_sp->SetWatchVariable(true);
957 if (var_sp && var_sp->GetDeclaration().GetFile()) {
958 StreamString ss;
959 // True to show fullpath for declaration file.
960 var_sp->GetDeclaration().DumpStopContext(&ss, true);
961 watch_sp->SetDeclInfo(std::string(ss.GetString()));
962 }
963 output_stream.Printf("Watchpoint created: ");
964 watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
965 output_stream.EOL();
967 } else {
969 "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64
970 ", variable expression='%s').\n",
971 addr, (uint64_t)size, command.GetArgumentAtIndex(0));
972 if (error.AsCString(nullptr))
973 result.AppendError(error.AsCString());
974 }
976 return result.Succeeded();
977 }
978
979private:
980 OptionGroupOptions m_option_group;
981 OptionGroupWatchpoint m_option_watchpoint;
982};
983
984// CommandObjectWatchpointSetExpression
985#pragma mark Set
986
988public:
991 interpreter, "watchpoint set expression",
992 "Set a watchpoint on an address by supplying an expression. "
993 "Use the '-w' option to specify the type of watchpoint and "
994 "the '-s' option to specify the byte size to watch for. "
995 "If no '-w' option is specified, it defaults to write. "
996 "If no '-s' option is specified, it defaults to the target's "
997 "pointer byte size. "
998 "Note that there are limited hardware resources for watchpoints. "
999 "If watchpoint setting fails, consider disable/delete existing "
1000 "ones "
1001 "to free up resources.",
1002 "",
1003 eCommandRequiresFrame | eCommandTryTargetAPILock |
1004 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
1005 SetHelpLong(
1006 R"(
1007Examples:
1008
1009(lldb) watchpoint set expression -w write -s 1 -- foo + 32
1010
1011 Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
1012
1014 CommandArgumentData expression_arg;
1015
1016 // Define the only variant of this arg.
1017 expression_arg.arg_type = eArgTypeExpression;
1018 expression_arg.arg_repetition = eArgRepeatPlain;
1019
1020 // Push the only variant into the argument entry.
1021 arg.push_back(expression_arg);
1022
1023 // Push the data for the only argument into the m_arguments vector.
1024 m_arguments.push_back(arg);
1025
1026 // Absorb the '-w' and '-s' options into our option group.
1027 m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
1029 m_option_group.Finalize();
1030 }
1032 ~CommandObjectWatchpointSetExpression() override = default;
1034 // Overrides base class's behavior where WantsCompletion =
1035 // !WantsRawCommandString.
1036 bool WantsCompletion() override { return true; }
1037
1038 Options *GetOptions() override { return &m_option_group; }
1039
1040protected:
1041 bool DoExecute(llvm::StringRef raw_command,
1042 CommandReturnObject &result) override {
1043 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
1044 m_option_group.NotifyOptionParsingStarting(
1045 &exe_ctx); // This is a raw command, so notify the option group
1046
1047 Target *target = GetDebugger().GetSelectedTarget().get();
1048 StackFrame *frame = m_exe_ctx.GetFramePtr();
1049
1050 OptionsWithRaw args(raw_command);
1051
1052 llvm::StringRef expr = args.GetRawPart();
1053
1054 if (args.HasArgs())
1055 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
1056 exe_ctx))
1057 return false;
1058
1059 // If no argument is present, issue an error message. There's no way to
1060 // set a watchpoint.
1061 if (raw_command.trim().empty()) {
1062 result.AppendError("required argument missing; specify an expression "
1063 "to evaluate into the address to watch for");
1064 return false;
1065 }
1066
1067 // If no '-w' is specified, default to '-w write'.
1068 if (!m_option_watchpoint.watch_type_specified) {
1069 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
1070 }
1071
1072 // We passed the sanity check for the command. Proceed to set the
1073 // watchpoint now.
1074 lldb::addr_t addr = 0;
1075 size_t size = 0;
1076
1077 ValueObjectSP valobj_sp;
1078
1079 // Use expression evaluation to arrive at the address to watch.
1081 options.SetCoerceToId(false);
1082 options.SetUnwindOnError(true);
1083 options.SetKeepInMemory(false);
1084 options.SetTryAllThreads(true);
1085 options.SetTimeout(std::nullopt);
1086
1087 ExpressionResults expr_result =
1088 target->EvaluateExpression(expr, frame, valobj_sp, options);
1089 if (expr_result != eExpressionCompleted) {
1090 result.AppendError("expression evaluation of address to watch failed");
1091 result.AppendErrorWithFormat("expression evaluated: \n%s", expr.data());
1092 if (valobj_sp && !valobj_sp->GetError().Success())
1093 result.AppendError(valobj_sp->GetError().AsCString());
1094 return false;
1095 }
1096
1097 // Get the address to watch.
1098 bool success = false;
1099 addr = valobj_sp->GetValueAsUnsigned(0, &success);
1100 if (!success) {
1101 result.AppendError("expression did not evaluate to an address");
1102 return false;
1103 }
1104
1105 if (m_option_watchpoint.watch_size != 0)
1106 size = m_option_watchpoint.watch_size;
1107 else
1108 size = target->GetArchitecture().GetAddressByteSize();
1109
1110 // Now it's time to create the watchpoint.
1111 uint32_t watch_type = m_option_watchpoint.watch_type;
1112
1113 // Fetch the type from the value object, the type of the watched object is
1114 // the pointee type
1115 /// of the expression, so convert to that if we found a valid type.
1116 CompilerType compiler_type(valobj_sp->GetCompilerType());
1117
1118 Status error;
1119 WatchpointSP watch_sp =
1120 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error);
1121 if (watch_sp) {
1122 watch_sp->SetWatchSpec(std::string(expr));
1123 Stream &output_stream = result.GetOutputStream();
1124 output_stream.Printf("Watchpoint created: ");
1125 watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1126 output_stream.EOL();
1128 } else {
1129 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
1130 ", size=%" PRIu64 ").\n",
1131 addr, (uint64_t)size);
1132 if (error.AsCString(nullptr))
1133 result.AppendError(error.AsCString());
1134 }
1136 return result.Succeeded();
1137 }
1138
1139private:
1140 OptionGroupOptions m_option_group;
1141 OptionGroupWatchpoint m_option_watchpoint;
1142};
1143
1144// CommandObjectWatchpointSet
1145#pragma mark Set
1146
1148public:
1151 interpreter, "watchpoint set", "Commands for setting a watchpoint.",
1152 "watchpoint set <subcommand> [<subcommand-options>]") {
1153
1154 LoadSubCommand(
1155 "variable",
1156 CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter)));
1157 LoadSubCommand(
1158 "expression",
1159 CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter)));
1160 }
1161
1162 ~CommandObjectWatchpointSet() override = default;
1163};
1164
1165// CommandObjectMultiwordWatchpoint
1166#pragma mark MultiwordWatchpoint
1167
1169 CommandInterpreter &interpreter)
1170 : CommandObjectMultiword(interpreter, "watchpoint",
1171 "Commands for operating on watchpoints.",
1172 "watchpoint <subcommand> [<command-options>]") {
1173 CommandObjectSP list_command_object(
1174 new CommandObjectWatchpointList(interpreter));
1175 CommandObjectSP enable_command_object(
1176 new CommandObjectWatchpointEnable(interpreter));
1177 CommandObjectSP disable_command_object(
1178 new CommandObjectWatchpointDisable(interpreter));
1179 CommandObjectSP delete_command_object(
1180 new CommandObjectWatchpointDelete(interpreter));
1181 CommandObjectSP ignore_command_object(
1182 new CommandObjectWatchpointIgnore(interpreter));
1183 CommandObjectSP command_command_object(
1184 new CommandObjectWatchpointCommand(interpreter));
1185 CommandObjectSP modify_command_object(
1186 new CommandObjectWatchpointModify(interpreter));
1187 CommandObjectSP set_command_object(
1188 new CommandObjectWatchpointSet(interpreter));
1189
1190 list_command_object->SetCommandName("watchpoint list");
1191 enable_command_object->SetCommandName("watchpoint enable");
1192 disable_command_object->SetCommandName("watchpoint disable");
1193 delete_command_object->SetCommandName("watchpoint delete");
1194 ignore_command_object->SetCommandName("watchpoint ignore");
1195 command_command_object->SetCommandName("watchpoint command");
1196 modify_command_object->SetCommandName("watchpoint modify");
1197 set_command_object->SetCommandName("watchpoint set");
1198
1199 LoadSubCommand("list", list_command_object);
1200 LoadSubCommand("enable", enable_command_object);
1201 LoadSubCommand("disable", disable_command_object);
1202 LoadSubCommand("delete", delete_command_object);
1203 LoadSubCommand("ignore", ignore_command_object);
1204 LoadSubCommand("command", command_command_object);
1205 LoadSubCommand("modify", modify_command_object);
1206 LoadSubCommand("set", set_command_object);
1207}
1208
static bool CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result)
static void AddWatchpointDescription(Stream &s, Watchpoint &wp, lldb::DescriptionLevel level)
static int32_t WithRSAIndex(llvm::StringRef Arg)
static const char * RSA[4]
static llvm::raw_ostream & error(Stream &strm)
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void OptionParsingStarting(ExecutionContext *execution_context) override
bool DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectWatchpointDelete(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
~CommandObjectWatchpointDelete() override=default
~CommandObjectWatchpointDisable() override=default
bool DoExecute(Args &command, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
CommandObjectWatchpointDisable(CommandInterpreter &interpreter)
CommandObjectWatchpointEnable(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
bool DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectWatchpointEnable() override=default
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
CommandObjectWatchpointIgnore(CommandInterpreter &interpreter)
bool DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectWatchpointIgnore() override=default
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
CommandObjectWatchpointList(CommandInterpreter &interpreter)
~CommandObjectWatchpointList() override=default
bool DoExecute(Args &command, CommandReturnObject &result) override
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
~CommandObjectWatchpointModify() override=default
bool DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectWatchpointModify(CommandInterpreter &interpreter)
CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter)
CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter)
~CommandObjectWatchpointSet() override=default
CommandObjectWatchpointSet(CommandInterpreter &interpreter)
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
Definition: ArchSpec.cpp:694
A command line argument class.
Definition: Args.h:33
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:116
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:128
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:264
bool empty() const
Definition: Args.h:118
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter)
static bool VerifyWatchpointIDs(Target *target, Args &args, std::vector< uint32_t > &wp_ids)
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
std::vector< CommandArgumentData > CommandArgumentEntry
static void AddIDsArgumentData(CommandArgumentEntry &arg, lldb::CommandArgumentType ID, lldb::CommandArgumentType IDRange)
void AppendMessage(llvm::StringRef in_string)
void void AppendError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
Generic representation of a type in a programming language.
Definition: CompilerType.h:36
std::optional< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
"lldb/Utility/ArgCompletionRequest.h"
A uniqued constant string class.
Definition: ConstString.h:39
void SetUnwindOnError(bool unwind=false)
Definition: Target.h:324
void SetKeepInMemory(bool keep=true)
Definition: Target.h:334
void SetCoerceToId(bool coerce=true)
Definition: Target.h:320
void SetTryAllThreads(bool try_others=true)
Definition: Target.h:357
void SetTimeout(const Timeout< std::micro > &timeout)
Definition: Target.h:345
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
void FindGlobalVariables(ConstString name, size_t max_matches, VariableList &variable_list) const
Find global and static variables by name.
Definition: ModuleList.cpp:492
A pair of an option list with a 'raw' string as a suffix.
Definition: Args.h:315
A command line option parsing protocol class.
Definition: Options.h:58
void NotifyOptionParsingStarting(ExecutionContext *execution_context)
Definition: Options.cpp:33
This base class provides an interface to stack frames.
Definition: StackFrame.h:41
@ eExpressionPathOptionsAllowDirectIVarAccess
Definition: StackFrame.h:48
lldb::ValueObjectSP GetValueForVariableExpressionPath(llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Status &error)
Create a ValueObject for a variable name / pathname, possibly including simple dereference/child sele...
Definition: StackFrame.cpp:508
An error handling class.
Definition: Status.h:44
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:128
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition: Stream.cpp:171
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition: Stream.cpp:168
lldb::WatchpointSP CreateWatchpoint(lldb::addr_t addr, size_t size, const CompilerType *type, uint32_t kind, Status &error)
Definition: Target.cpp:812
bool IgnoreWatchpointByID(lldb::watch_id_t watch_id, uint32_t ignore_count)
Definition: Target.cpp:1355
bool EnableWatchpointByID(lldb::watch_id_t watch_id)
Definition: Target.cpp:1320
const lldb::ProcessSP & GetProcessSP() const
Definition: Target.cpp:218
bool RemoveAllWatchpoints(bool end_to_end=true)
Definition: Target.cpp:1173
bool RemoveWatchpointByID(lldb::watch_id_t watch_id)
Definition: Target.cpp:1339
bool DisableAllWatchpoints(bool end_to_end=true)
Definition: Target.cpp:1202
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:948
const ArchSpec & GetArchitecture() const
Definition: Target.h:990
WatchpointList & GetWatchpointList()
Definition: Target.h:742
bool IgnoreAllWatchpoints(uint32_t ignore_count)
Definition: Target.cpp:1284
bool DisableWatchpointByID(lldb::watch_id_t watch_id)
Definition: Target.cpp:1301
lldb::WatchpointSP GetLastCreatedWatchpoint()
Definition: Target.h:738
bool EnableAllWatchpoints(bool end_to_end=true)
Definition: Target.cpp:1229
lldb::ExpressionResults EvaluateExpression(llvm::StringRef expression, ExecutionContextScope *exe_scope, lldb::ValueObjectSP &result_valobj_sp, const EvaluateExpressionOptions &options=EvaluateExpressionOptions(), std::string *fixed_expression=nullptr, ValueObject *ctx_obj=nullptr)
Definition: Target.cpp:2543
A collection of ValueObject values that.
lldb::ValueObjectSP GetValueObjectAtIndex(size_t idx)
static Status GetValuesForVariableExpressionPath(llvm::StringRef variable_expr_path, ExecutionContextScope *scope, GetVariableCallback callback, void *baton, VariableList &variable_list, ValueObjectList &valobj_list)
Definition: Variable.cpp:322
This class is used by Watchpoint to manage a list of watchpoints,.
lldb::WatchpointSP GetByIndex(uint32_t i)
Returns a shared pointer to the watchpoint with index i.
lldb::WatchpointSP FindByID(lldb::watch_id_t watchID) const
Returns a shared pointer to the watchpoint with id watchID, const version.
void GetListMutex(std::unique_lock< std::recursive_mutex > &lock)
Sets the passed in Locker to hold the Watchpoint List mutex.
size_t GetSize() const
Returns the number of elements in this watchpoint list.
void GetDescription(Stream *s, lldb::DescriptionLevel level)
Definition: Watchpoint.cpp:149
#define LLDB_OPT_SET_1
Definition: lldb-defines.h:102
#define LLDB_OPT_SET_ALL
Definition: lldb-defines.h:101
#define UINT32_MAX
Definition: lldb-defines.h:19
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:43
@ eAddressTypeLoad
Address is an address as in the current target inferior process.
Definition: SBAddress.h:15
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
@ eDescriptionLevelBrief
@ eDescriptionLevelFull
@ eDescriptionLevelVerbose
ExpressionResults
The results of expression evaluation.
@ eExpressionCompleted
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
@ eArgTypeExpression
@ eArgTypeWatchpointID
@ eArgTypeWatchpointIDRange
uint64_t addr_t
Definition: lldb-types.h:83
@ eNoDynamicValues
Used to build individual command argument lists.
Definition: CommandObject.h:93