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 <memory>
13#include <vector>
14
15#include "llvm/ADT/StringRef.h"
16
27#include "lldb/Target/Target.h"
30
31using namespace lldb;
32using namespace lldb_private;
33
36 s.IndentMore();
37 wp.GetDescription(&s, level);
38 s.IndentLess();
39 s.EOL();
40}
41
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;
49 }
50 // Target passes our checks, return true.
51 return true;
52}
53
54// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
55static const char *RSA[4] = {"-", "to", "To", "TO"};
56
57// Return the index to RSA if found; otherwise -1 is returned.
58static int32_t WithRSAIndex(llvm::StringRef Arg) {
59
60 uint32_t i;
61 for (i = 0; i < 4; ++i)
62 if (Arg.contains(RSA[i]))
63 return i;
64 return -1;
65}
66
67// Return true if wp_ids is successfully populated with the watch ids. False
68// otherwise.
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();
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) {
155 }
156
157 ~CommandObjectWatchpointList() override = default;
158
159 Options *GetOptions() override { return &m_options; }
160
161 class CommandOptions : public Options {
162 public:
163 CommandOptions() = default;
164
165 ~CommandOptions() override = default;
166
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;
171
172 switch (short_option) {
173 case 'b':
175 break;
176 case 'f':
178 break;
179 case 'v':
181 break;
182 default:
183 llvm_unreachable("Unimplemented option");
184 }
185
186 return error;
187 }
188
189 void OptionParsingStarting(ExecutionContext *execution_context) override {
191 }
192
193 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
194 return llvm::ArrayRef(g_watchpoint_list_options);
195 }
196
197 // Instance variables to hold the values for command options.
198
200 };
201
202protected:
203 void DoExecute(Args &command, CommandReturnObject &result) override {
204 Target *target = GetTarget();
205 assert(target && "target guaranteed by eCommandRequiresTarget");
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();
210
211 if (num_supported_hardware_watchpoints)
213 "Number of supported hardware watchpoints: {0}",
214 *num_supported_hardware_watchpoints);
215 }
216 }
217
218 const WatchpointList &watchpoints = target->GetWatchpointList();
219
220 std::unique_lock<std::recursive_mutex> lock;
221 target->GetWatchpointList().GetListMutex(lock);
222
223 size_t num_watchpoints = watchpoints.GetSize();
224
225 if (num_watchpoints == 0) {
226 result.AppendMessage("No watchpoints currently set.");
228 return;
229 }
230
231 Stream &output_stream = result.GetOutputStream();
232
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);
239 }
241 } else {
242 // Particular watchpoints selected; enable them.
243 std::vector<uint32_t> wp_ids;
245 *target, command, wp_ids)) {
246 result.AppendError("invalid watchpoints specification");
247 return;
248 }
249
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]);
253 if (watch_sp)
254 AddWatchpointDescription(output_stream, *watch_sp, m_options.m_level);
256 }
257 }
258 }
259
260private:
262};
263
264// CommandObjectWatchpointEnable
265#pragma mark Enable
266
268public:
270 : CommandObjectParsed(interpreter, "enable",
271 "Enable the specified disabled watchpoint(s). If "
272 "no watchpoints are specified, enable all of them.",
273 nullptr, eCommandRequiresTarget) {
275 }
276
277 ~CommandObjectWatchpointEnable() override = default;
278
279 void
286
287protected:
288 void DoExecute(Args &command, CommandReturnObject &result) override {
289 Target *target = GetTarget();
290 assert(target && "target guaranteed by eCommandRequiresTarget");
291 if (!CheckTargetForWatchpointOperations(*target, result))
292 return;
293
294 std::unique_lock<std::recursive_mutex> lock;
295 target->GetWatchpointList().GetListMutex(lock);
296
297 const WatchpointList &watchpoints = target->GetWatchpointList();
298
299 size_t num_watchpoints = watchpoints.GetSize();
300
301 if (num_watchpoints == 0) {
302 result.AppendError("no watchpoints exist to be enabled");
303 return;
304 }
305
306 if (command.GetArgumentCount() == 0) {
307 // No watchpoint selected; enable all currently set watchpoints.
308 target->EnableAllWatchpoints();
310 "All watchpoints enabled. ({0} watchpoints)",
311 (uint64_t)num_watchpoints);
313 } else {
314 // Particular watchpoints selected; enable them.
315 std::vector<uint32_t> wp_ids;
317 *target, command, wp_ids)) {
318 result.AppendError("invalid watchpoints specification");
319 return;
320 }
321
322 int count = 0;
323 const size_t size = wp_ids.size();
324 for (size_t i = 0; i < size; ++i)
325 if (target->EnableWatchpointByID(wp_ids[i]))
326 ++count;
327 result.AppendMessageWithFormatv("{0} watchpoints enabled.", count);
329 }
330 }
331};
332
333// CommandObjectWatchpointDisable
334#pragma mark Disable
335
337public:
339 : CommandObjectParsed(interpreter, "watchpoint disable",
340 "Disable the specified watchpoint(s) without "
341 "removing it/them. If no watchpoints are "
342 "specified, disable them all.",
343 nullptr, eCommandRequiresTarget) {
345 }
346
348
349 void
356
357protected:
358 void DoExecute(Args &command, CommandReturnObject &result) override {
359 Target *target = GetTarget();
360 assert(target && "target guaranteed by eCommandRequiresTarget");
361 if (!CheckTargetForWatchpointOperations(*target, result))
362 return;
363
364 std::unique_lock<std::recursive_mutex> lock;
365 target->GetWatchpointList().GetListMutex(lock);
366
367 const WatchpointList &watchpoints = target->GetWatchpointList();
368 size_t num_watchpoints = watchpoints.GetSize();
369
370 if (num_watchpoints == 0) {
371 result.AppendError("no watchpoints exist to be disabled");
372 return;
373 }
374
375 if (command.GetArgumentCount() == 0) {
376 // No watchpoint selected; disable all currently set watchpoints.
377 if (target->DisableAllWatchpoints()) {
379 "All watchpoints disabled. ({0} watchpoints)",
380 (uint64_t)num_watchpoints);
382 } else {
383 result.AppendError("Disable all watchpoints failed\n");
384 }
385 } else {
386 // Particular watchpoints selected; disable them.
387 std::vector<uint32_t> wp_ids;
389 *target, command, wp_ids)) {
390 result.AppendError("invalid watchpoints specification");
391 return;
392 }
393
394 int count = 0;
395 const size_t size = wp_ids.size();
396 for (size_t i = 0; i < size; ++i)
397 if (target->DisableWatchpointByID(wp_ids[i]))
398 ++count;
399 result.AppendMessageWithFormatv("{0} watchpoints disabled.\n", count);
401 }
402 }
403};
404
405// CommandObjectWatchpointDelete
406#define LLDB_OPTIONS_watchpoint_delete
407#include "CommandOptions.inc"
408
409// CommandObjectWatchpointDelete
410#pragma mark Delete
411
413public:
415 : CommandObjectParsed(interpreter, "watchpoint delete",
416 "Delete the specified watchpoint(s). If no "
417 "watchpoints are specified, delete them all.",
418 nullptr, eCommandRequiresTarget) {
420 }
421
422 ~CommandObjectWatchpointDelete() override = default;
423
424 void
431
432 Options *GetOptions() override { return &m_options; }
433
434 class CommandOptions : public Options {
435 public:
436 CommandOptions() = default;
437
438 ~CommandOptions() override = default;
439
440 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
441 ExecutionContext *execution_context) override {
442 const int short_option = m_getopt_table[option_idx].val;
443
444 switch (short_option) {
445 case 'f':
446 m_force = true;
447 break;
448 default:
449 llvm_unreachable("Unimplemented option");
450 }
451
452 return {};
453 }
454
455 void OptionParsingStarting(ExecutionContext *execution_context) override {
456 m_force = false;
457 }
458
459 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
460 return llvm::ArrayRef(g_watchpoint_delete_options);
461 }
462
463 // Instance variables to hold the values for command options.
464 bool m_force = false;
465 };
466
467protected:
468 void DoExecute(Args &command, CommandReturnObject &result) override {
469 Target *target = GetTarget();
470 assert(target && "target guaranteed by eCommandRequiresTarget");
471 if (!CheckTargetForWatchpointOperations(*target, result))
472 return;
473
474 std::unique_lock<std::recursive_mutex> lock;
475 target->GetWatchpointList().GetListMutex(lock);
476
477 const WatchpointList &watchpoints = target->GetWatchpointList();
478
479 size_t num_watchpoints = watchpoints.GetSize();
480
481 if (num_watchpoints == 0) {
482 result.AppendError("no watchpoints exist to be deleted");
483 return;
484 }
485
486 if (command.empty()) {
487 if (!m_options.m_force &&
488 !m_interpreter.Confirm(
489 "About to delete all watchpoints, do you want to do that?",
490 true)) {
491 result.AppendMessage("Operation cancelled...");
492 } else {
493 target->RemoveAllWatchpoints();
495 "All watchpoints removed. ({0} watchpoints)",
496 (uint64_t)num_watchpoints);
497 }
499 return;
500 }
501
502 // Particular watchpoints selected; delete them.
503 std::vector<uint32_t> wp_ids;
505 wp_ids)) {
506 result.AppendError("invalid watchpoints specification");
507 return;
508 }
509
510 int count = 0;
511 const size_t size = wp_ids.size();
512 for (size_t i = 0; i < size; ++i)
513 if (target->RemoveWatchpointByID(wp_ids[i]))
514 ++count;
515 result.AppendMessageWithFormatv("{0} watchpoints deleted.", count);
517 }
518
519private:
521};
522
523// CommandObjectWatchpointIgnore
524
525#pragma mark Ignore::CommandOptions
526#define LLDB_OPTIONS_watchpoint_ignore
527#include "CommandOptions.inc"
528
530public:
532 : CommandObjectParsed(interpreter, "watchpoint ignore",
533 "Set ignore count on the specified watchpoint(s). "
534 "If no watchpoints are specified, set them all.",
535 nullptr, eCommandRequiresTarget) {
537 }
538
539 ~CommandObjectWatchpointIgnore() override = default;
540
541 void
548
549 Options *GetOptions() override { return &m_options; }
550
551 class CommandOptions : public Options {
552 public:
553 CommandOptions() = default;
554
555 ~CommandOptions() override = default;
556
557 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
558 ExecutionContext *execution_context) override {
560 const int short_option = m_getopt_table[option_idx].val;
561
562 switch (short_option) {
563 case 'i':
564 if (option_arg.getAsInteger(0, m_ignore_count))
565 error = Status::FromErrorStringWithFormat("invalid ignore count '%s'",
566 option_arg.str().c_str());
567 break;
568 default:
569 llvm_unreachable("Unimplemented option");
570 }
571
572 return error;
573 }
574
575 void OptionParsingStarting(ExecutionContext *execution_context) override {
576 m_ignore_count = 0;
577 }
578
579 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
580 return llvm::ArrayRef(g_watchpoint_ignore_options);
581 }
582
583 // Instance variables to hold the values for command options.
584
585 uint32_t m_ignore_count = 0;
586 };
587
588protected:
589 void DoExecute(Args &command, CommandReturnObject &result) override {
590 Target *target = GetTarget();
591 assert(target && "target guaranteed by eCommandRequiresTarget");
592 if (!CheckTargetForWatchpointOperations(*target, result))
593 return;
594
595 std::unique_lock<std::recursive_mutex> lock;
596 target->GetWatchpointList().GetListMutex(lock);
597
598 const WatchpointList &watchpoints = target->GetWatchpointList();
599
600 size_t num_watchpoints = watchpoints.GetSize();
601
602 if (num_watchpoints == 0) {
603 result.AppendError("no watchpoints exist to be ignored");
604 return;
605 }
606
607 if (command.GetArgumentCount() == 0) {
608 target->IgnoreAllWatchpoints(m_options.m_ignore_count);
610 "All watchpoints ignored. ({0} watchpoints)",
611 (uint64_t)num_watchpoints);
613 } else {
614 // Particular watchpoints selected; ignore them.
615 std::vector<uint32_t> wp_ids;
617 *target, command, wp_ids)) {
618 result.AppendError("invalid watchpoints specification");
619 return;
620 }
621
622 int count = 0;
623 const size_t size = wp_ids.size();
624 for (size_t i = 0; i < size; ++i)
625 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
626 ++count;
627 result.AppendMessageWithFormatv("{0} watchpoints ignored.", count);
629 }
630 }
631
632private:
634};
635
636// CommandObjectWatchpointModify
637
638#pragma mark Modify::CommandOptions
639#define LLDB_OPTIONS_watchpoint_modify
640#include "CommandOptions.inc"
641
642#pragma mark Modify
643
645public:
648 interpreter, "watchpoint modify",
649 "Modify the options on a watchpoint or set of watchpoints in the "
650 "executable. "
651 "If no watchpoint is specified, act on the last created "
652 "watchpoint. "
653 "Passing an empty argument clears the modification.",
654 nullptr, eCommandRequiresTarget) {
656 }
657
658 ~CommandObjectWatchpointModify() override = default;
659
660 void
667
668 Options *GetOptions() override { return &m_options; }
669
670 class CommandOptions : public Options {
671 public:
672 CommandOptions() = default;
673
674 ~CommandOptions() override = default;
675
676 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
677 ExecutionContext *execution_context) override {
679 const int short_option = m_getopt_table[option_idx].val;
680
681 switch (short_option) {
682 case 'c':
683 m_condition = std::string(option_arg);
684 m_condition_passed = true;
685 break;
686 default:
687 llvm_unreachable("Unimplemented option");
688 }
689
690 return error;
691 }
692
693 void OptionParsingStarting(ExecutionContext *execution_context) override {
694 m_condition.clear();
695 m_condition_passed = false;
696 }
697
698 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
699 return llvm::ArrayRef(g_watchpoint_modify_options);
700 }
701
702 // Instance variables to hold the values for command options.
703
704 std::string m_condition;
705 bool m_condition_passed = false;
706 };
707
708protected:
709 void DoExecute(Args &command, CommandReturnObject &result) override {
710 Target *target = GetTarget();
711 assert(target && "target guaranteed by eCommandRequiresTarget");
712 if (!CheckTargetForWatchpointOperations(*target, result))
713 return;
714
715 std::unique_lock<std::recursive_mutex> lock;
716 target->GetWatchpointList().GetListMutex(lock);
717
718 const WatchpointList &watchpoints = target->GetWatchpointList();
719
720 size_t num_watchpoints = watchpoints.GetSize();
721
722 if (num_watchpoints == 0) {
723 result.AppendError("no watchpoints exist to be modified");
724 return;
725 }
726
727 if (command.GetArgumentCount() == 0) {
728 WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
729 watch_sp->SetCondition(m_options.m_condition.c_str());
731 } else {
732 // Particular watchpoints selected; set condition on them.
733 std::vector<uint32_t> wp_ids;
735 *target, command, wp_ids)) {
736 result.AppendError("invalid watchpoints specification");
737 return;
738 }
739
740 int count = 0;
741 const size_t size = wp_ids.size();
742 for (size_t i = 0; i < size; ++i) {
743 WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]);
744 if (watch_sp) {
745 watch_sp->SetCondition(m_options.m_condition.c_str());
746 ++count;
747 }
748 }
749 result.AppendMessageWithFormatv("{0} watchpoints modified.", count);
751 }
752 }
753
754private:
756};
757
758// CommandObjectWatchpointSetVariable
759#pragma mark SetVariable
760
762public:
765 interpreter, "watchpoint set variable",
766 "Set a watchpoint on a variable. "
767 "Use the '-w' option to specify the type of watchpoint and "
768 "the '-s' option to specify the byte size to watch for. "
769 "If no '-w' option is specified, it defaults to modify. "
770 "If no '-s' option is specified, it defaults to the variable's "
771 "byte size. "
772 "Note that there are limited hardware resources for watchpoints. "
773 "If watchpoint setting fails, consider disable/delete existing "
774 "ones "
775 "to free up resources.",
776 nullptr,
777 eCommandRequiresFrame | eCommandTryTargetAPILock |
778 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
780 R"(
781Examples:
782
783(lldb) watchpoint set variable -w read_write my_global_var
784
785)"
786 " Watches my_global_var for read/write access, with the region to watch \
787corresponding to the byte size of the data type.");
788
790
791 // Absorb the '-w' and '-s' options into our option group.
793 m_option_group.Finalize();
794 }
795
797
798 Options *GetOptions() override { return &m_option_group; }
799
800protected:
801 static size_t GetVariableCallback(void *baton, const char *name,
802 VariableList &variable_list) {
803 size_t old_size = variable_list.GetSize();
804 Target *target = static_cast<Target *>(baton);
805 if (target)
807 variable_list);
808 return variable_list.GetSize() - old_size;
809 }
810
811 void DoExecute(Args &command, CommandReturnObject &result) override {
812 Target *target = GetTarget();
813 assert(target && "target guaranteed by eCommandRequiresTarget");
814 StackFrame *frame = m_exe_ctx.GetFramePtr();
815
816 // If no argument is present, issue an error message. There's no way to
817 // set a watchpoint.
818 if (command.GetArgumentCount() <= 0) {
819 result.AppendError("required argument missing; "
820 "specify your program variable to watch for");
821 return;
822 }
823
824 // If no '-w' is specified, default to '-w modify'.
825 if (!m_option_watchpoint.watch_type_specified) {
826 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify;
827 }
828
829 // We passed the sanity check for the command. Proceed to set the
830 // watchpoint now.
831 size_t size = 0;
832
833 VariableSP var_sp;
834 ValueObjectSP valobj_sp;
835 Stream &output_stream = result.GetOutputStream();
836
837 // A simple watch variable gesture allows only one argument.
838 if (command.GetArgumentCount() != 1) {
839 result.AppendError("specify exactly one variable to watch for");
840 return;
841 }
842
843 // Things have checked out ok...
845 uint32_t expr_path_options =
848 valobj_sp = frame->GetValueForVariableExpressionPath(
849 command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
850 var_sp, error);
851
852 if (!valobj_sp) {
853 // Not in the frame; let's check the globals.
854
855 VariableList variable_list;
856 ValueObjectList valobj_list;
857
859 command.GetArgumentAtIndex(0),
860 m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target,
861 variable_list, valobj_list));
862
863 if (valobj_list.GetSize())
864 valobj_sp = valobj_list.GetValueObjectAtIndex(0);
865 }
866
867 CompilerType compiler_type;
868
869 if (!valobj_sp) {
870 const char *error_cstr = error.AsCString(nullptr);
871 if (error_cstr)
872 result.AppendError(error_cstr);
873 else
874 result.AppendErrorWithFormat("unable to find any variable "
875 "expression path that matches '%s'",
876 command.GetArgumentAtIndex(0));
877 return;
878 }
879 auto [addr, addr_type] = valobj_sp->GetAddressOf(false);
880 if (addr_type == eAddressTypeLoad) {
881 // We're in business.
882 // Find out the size of this variable.
883 size =
884 m_option_watchpoint.watch_size.GetCurrentValue() == 0
885 ? llvm::expectedToOptional(valobj_sp->GetByteSize()).value_or(0)
886 : m_option_watchpoint.watch_size.GetCurrentValue();
887 }
888 compiler_type = valobj_sp->GetCompilerType();
889
890 // Now it's time to create the watchpoint.
891 uint32_t watch_type = 0;
892 switch (m_option_watchpoint.watch_type) {
894 watch_type |= LLDB_WATCH_TYPE_MODIFY;
895 break;
897 watch_type |= LLDB_WATCH_TYPE_READ;
898 break;
901 break;
903 watch_type |= LLDB_WATCH_TYPE_WRITE;
904 break;
906 break;
907 };
908
909 error.Clear();
910 WatchpointSP watch_sp =
911 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error);
912 if (!watch_sp) {
914 "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64
915 ", variable expression='%s')",
916 addr, static_cast<uint64_t>(size), command.GetArgumentAtIndex(0));
917 if (const char *error_message = error.AsCString(nullptr))
918 result.AppendError(error_message);
919 return;
920 }
921
922 watch_sp->SetWatchSpec(command.GetArgumentAtIndex(0));
923 watch_sp->SetWatchVariable(true);
924 if (var_sp) {
925 if (var_sp->GetDeclaration().GetFile()) {
926 StreamString ss;
927 // True to show fullpath for declaration file.
928 var_sp->GetDeclaration().DumpStopContext(&ss, true);
929 watch_sp->SetDeclInfo(std::string(ss.GetString()));
930 }
931 if (var_sp->GetScope() == eValueTypeVariableLocal)
932 watch_sp->SetupVariableWatchpointDisabler(m_exe_ctx.GetFrameSP());
933 }
934 output_stream.Printf("Watchpoint created: ");
935 watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
936 output_stream.EOL();
938 }
939
940private:
941 OptionGroupOptions m_option_group;
942 OptionGroupWatchpoint m_option_watchpoint;
943};
944
945// CommandObjectWatchpointSetExpression
946#pragma mark Set
947
949public:
952 interpreter, "watchpoint set expression",
953 "Set a watchpoint on an address by supplying an expression. "
954 "Use the '-l' option to specify the language of the expression. "
955 "Use the '-w' option to specify the type of watchpoint and "
956 "the '-s' option to specify the byte size to watch for. "
957 "If no '-w' option is specified, it defaults to modify. "
958 "If no '-s' option is specified, it defaults to the target's "
959 "pointer byte size. "
960 "Note that there are limited hardware resources for watchpoints. "
961 "If watchpoint setting fails, consider disable/delete existing "
962 "ones "
963 "to free up resources.",
964 "",
965 eCommandRequiresFrame | eCommandTryTargetAPILock |
966 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
968 R"(
969Examples:
970
971(lldb) watchpoint set expression -w modify -s 1 -- foo + 32
972
973 Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
974
976
977 // Absorb the '-w' and '-s' options into our option group.
980 m_option_group.Finalize();
981 }
983 ~CommandObjectWatchpointSetExpression() override = default;
985 // Overrides base class's behavior where WantsCompletion =
986 // !WantsRawCommandString.
987 bool WantsCompletion() override { return true; }
988
989 Options *GetOptions() override { return &m_option_group; }
990
991protected:
992 void DoExecute(llvm::StringRef raw_command,
993 CommandReturnObject &result) override {
994 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
995 m_option_group.NotifyOptionParsingStarting(
996 &exe_ctx); // This is a raw command, so notify the option group
997
998 Target *target = GetTarget();
999 assert(target && "target guaranteed by eCommandRequiresTarget");
1000 StackFrame *frame = m_exe_ctx.GetFramePtr();
1001
1002 OptionsWithRaw args(raw_command);
1003
1004 llvm::StringRef expr = args.GetRawPart();
1005
1006 if (args.HasArgs())
1007 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
1008 exe_ctx))
1009 return;
1010
1011 // If no argument is present, issue an error message. There's no way to
1012 // set a watchpoint.
1013 if (raw_command.trim().empty()) {
1014 result.AppendError("required argument missing; specify an expression "
1015 "to evaluate into the address to watch for");
1016 return;
1017 }
1018
1019 // If no '-w' is specified, default to '-w write'.
1020 if (!m_option_watchpoint.watch_type_specified) {
1021 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify;
1022 }
1023
1024 // We passed the sanity check for the command. Proceed to set the
1025 // watchpoint now.
1026 lldb::addr_t addr = 0;
1027 size_t size = 0;
1028
1029 ValueObjectSP valobj_sp;
1030
1031 // Use expression evaluation to arrive at the address to watch.
1032 EvaluateExpressionOptions options;
1033 options.SetCoerceToId(false);
1034 options.SetUnwindOnError(true);
1035 options.SetKeepInMemory(false);
1036 options.SetTryAllThreads(true);
1037 options.SetTimeout(std::nullopt);
1038 if (m_option_watchpoint.language_type != eLanguageTypeUnknown)
1039 options.SetLanguage(m_option_watchpoint.language_type);
1040
1041 ExpressionResults expr_result =
1042 target->EvaluateExpression(expr, frame, valobj_sp, options);
1043 if (expr_result != eExpressionCompleted) {
1044 result.AppendError("expression evaluation of address to watch failed");
1045 result.AppendErrorWithFormat("expression evaluated: \n%s", expr.data());
1046 if (valobj_sp && !valobj_sp->GetError().Success())
1047 result.AppendError(valobj_sp->GetError().AsCString());
1048 return;
1049 }
1050
1051 // Get the address to watch.
1052 bool success = false;
1053 addr = valobj_sp->GetValueAsUnsigned(0, &success);
1054 if (!success) {
1055 result.AppendError("expression did not evaluate to an address");
1056 return;
1057 }
1058
1059 if (m_option_watchpoint.watch_size.GetCurrentValue() != 0)
1060 size = m_option_watchpoint.watch_size.GetCurrentValue();
1061 else
1062 size = target->GetArchitecture().GetAddressByteSize();
1063
1064 // Now it's time to create the watchpoint.
1065 uint32_t watch_type;
1066 switch (m_option_watchpoint.watch_type) {
1068 watch_type = LLDB_WATCH_TYPE_READ;
1069 break;
1071 watch_type = LLDB_WATCH_TYPE_WRITE;
1072 break;
1074 watch_type = LLDB_WATCH_TYPE_MODIFY;
1075 break;
1078 break;
1079 default:
1080 watch_type = LLDB_WATCH_TYPE_MODIFY;
1081 }
1082
1083 // Fetch the type from the value object, the type of the watched object is
1084 // the pointee type
1085 /// of the expression, so convert to that if we found a valid type.
1086 CompilerType compiler_type(valobj_sp->GetCompilerType());
1087
1088 std::optional<uint64_t> valobj_size =
1089 llvm::expectedToOptional(valobj_sp->GetByteSize());
1090 // Set the type as a uint8_t array if the size being watched is
1091 // larger than the ValueObject's size (which is probably the size
1092 // of a pointer).
1093 if (valobj_size && size > *valobj_size) {
1094 auto type_system = compiler_type.GetTypeSystem();
1095 if (type_system) {
1096 CompilerType clang_uint8_type =
1097 type_system->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8);
1098 compiler_type = clang_uint8_type.GetArrayType(size);
1099 }
1100 }
1101
1102 Status error;
1103 WatchpointSP watch_sp =
1104 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error);
1105 if (watch_sp) {
1106 watch_sp->SetWatchSpec(std::string(expr));
1107 Stream &output_stream = result.GetOutputStream();
1108 output_stream.Printf("Watchpoint created: ");
1109 watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1110 output_stream.EOL();
1112 } else {
1113 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
1114 ", size=%" PRIu64 ")",
1115 addr, (uint64_t)size);
1116 if (error.AsCString(nullptr))
1117 result.AppendError(error.AsCString());
1119 }
1120
1121private:
1122 OptionGroupOptions m_option_group;
1123 OptionGroupWatchpoint m_option_watchpoint;
1124};
1125
1126// CommandObjectWatchpointSet
1127#pragma mark Set
1128
1130public:
1133 interpreter, "watchpoint set", "Commands for setting a watchpoint.",
1134 "watchpoint set <subcommand> [<subcommand-options>]") {
1135
1137 "variable",
1140 "expression",
1142 }
1143
1144 ~CommandObjectWatchpointSet() override = default;
1145};
1146
1147// CommandObjectMultiwordWatchpoint
1148#pragma mark MultiwordWatchpoint
1149
1151 CommandInterpreter &interpreter)
1152 : CommandObjectMultiword(interpreter, "watchpoint",
1153 "Commands for operating on watchpoints.",
1154 "watchpoint <subcommand> [<command-options>]") {
1155 CommandObjectSP list_command_object(
1156 new CommandObjectWatchpointList(interpreter));
1157 CommandObjectSP enable_command_object(
1158 new CommandObjectWatchpointEnable(interpreter));
1159 CommandObjectSP disable_command_object(
1160 new CommandObjectWatchpointDisable(interpreter));
1161 CommandObjectSP delete_command_object(
1162 new CommandObjectWatchpointDelete(interpreter));
1163 CommandObjectSP ignore_command_object(
1164 new CommandObjectWatchpointIgnore(interpreter));
1165 CommandObjectSP command_command_object(
1166 new CommandObjectWatchpointCommand(interpreter));
1167 CommandObjectSP modify_command_object(
1168 new CommandObjectWatchpointModify(interpreter));
1169 CommandObjectSP set_command_object(
1170 new CommandObjectWatchpointSet(interpreter));
1171
1172 list_command_object->SetCommandName("watchpoint list");
1173 enable_command_object->SetCommandName("watchpoint enable");
1174 disable_command_object->SetCommandName("watchpoint disable");
1175 delete_command_object->SetCommandName("watchpoint delete");
1176 ignore_command_object->SetCommandName("watchpoint ignore");
1177 command_command_object->SetCommandName("watchpoint command");
1178 modify_command_object->SetCommandName("watchpoint modify");
1179 set_command_object->SetCommandName("watchpoint set");
1180
1181 LoadSubCommand("list", list_command_object);
1182 LoadSubCommand("enable", enable_command_object);
1183 LoadSubCommand("disable", disable_command_object);
1184 LoadSubCommand("delete", delete_command_object);
1185 LoadSubCommand("ignore", ignore_command_object);
1186 LoadSubCommand("command", command_command_object);
1187 LoadSubCommand("modify", modify_command_object);
1188 LoadSubCommand("set", set_command_object);
1189}
1190
static void AddWatchpointDescription(Stream &s, Watchpoint &wp, lldb::DescriptionLevel level)
static int32_t WithRSAIndex(llvm::StringRef Arg)
static bool CheckTargetForWatchpointOperations(Target &target, CommandReturnObject &result)
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
CommandObjectWatchpointDelete(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectWatchpointDelete() override=default
~CommandObjectWatchpointDisable() override=default
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
CommandObjectWatchpointDisable(CommandInterpreter &interpreter)
void DoExecute(Args &command, CommandReturnObject &result) override
CommandObjectWatchpointEnable(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The default version handles argument definitions that have only one argument type,...
~CommandObjectWatchpointEnable() override=default
void DoExecute(Args &command, CommandReturnObject &result) override
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 default version handles argument definitions that have only one argument type,...
CommandObjectWatchpointIgnore(CommandInterpreter &interpreter)
~CommandObjectWatchpointIgnore() override=default
void 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
CommandObjectWatchpointList(CommandInterpreter &interpreter)
~CommandObjectWatchpointList() override=default
void 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 default version handles argument definitions that have only one argument type,...
void DoExecute(Args &command, CommandReturnObject &result) override
~CommandObjectWatchpointModify() override=default
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:690
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:120
llvm::ArrayRef< ArgEntry > entries() const
Definition Args.h:132
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition Args.cpp:273
bool empty() const
Definition Args.h:122
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
CommandObjectMultiword(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
CommandObjectParsed(CommandInterpreter &interpreter, const char *name, const char *help=nullptr, const char *syntax=nullptr, uint32_t flags=0)
CommandObjectRaw(CommandInterpreter &interpreter, llvm::StringRef name, llvm::StringRef help="", llvm::StringRef syntax="", uint32_t flags=0)
virtual void SetHelpLong(llvm::StringRef str)
void AddSimpleArgumentList(lldb::CommandArgumentType arg_type, ArgumentRepetitionType repetition_type=eArgRepeatPlain)
void AddIDsArgumentData(IDType type)
CommandInterpreter & GetCommandInterpreter()
CommandInterpreter & m_interpreter
Target * GetTarget()
Get the target this command should operate on.
void AppendMessage(llvm::StringRef in_string)
void AppendError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void void AppendMessageWithFormatv(const char *format, Args &&...args)
TypeSystemSPWrapper GetTypeSystem() const
Accessors.
CompilerType GetArrayType(uint64_t size) const
"lldb/Utility/ArgCompletionRequest.h"
A uniqued constant string class.
Definition ConstString.h:40
void SetUnwindOnError(bool unwind=false)
Definition Target.h:396
void SetKeepInMemory(bool keep=true)
Definition Target.h:406
void SetCoerceToId(bool coerce=true)
Definition Target.h:392
void SetLanguage(lldb::LanguageType language_type)
Definition Target.h:360
void SetTryAllThreads(bool try_others=true)
Definition Target.h:429
void SetTimeout(const Timeout< std::micro > &timeout)
Definition Target.h:417
"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.
A command line option parsing protocol class.
Definition Options.h:58
void NotifyOptionParsingStarting(ExecutionContext *execution_context)
Definition Options.cpp:73
std::vector< Option > m_getopt_table
Definition Options.h:198
This base class provides an interface to stack frames.
Definition StackFrame.h:44
virtual lldb::ValueObjectSP GetValueForVariableExpressionPath(llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic, uint32_t options, lldb::VariableSP &var_sp, Status &error, lldb::DILMode mode=lldb::eDILModeFull)
Create a ValueObject for a variable name / pathname, possibly including simple dereference/child sele...
@ eExpressionPathOptionsAllowDirectIVarAccess
Definition StackFrame.h:56
An error handling class.
Definition Status.h:118
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
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:134
size_t EOL()
Output and End of Line character to the stream.
Definition Stream.cpp:155
void IndentLess(unsigned amount=2)
Decrement the current indentation level.
Definition Stream.cpp:204
void IndentMore(unsigned amount=2)
Increment the current indentation level.
Definition Stream.cpp:201
lldb::WatchpointSP CreateWatchpoint(lldb::addr_t addr, size_t size, const CompilerType *type, uint32_t kind, Status &error)
Definition Target.cpp:1023
bool IgnoreWatchpointByID(lldb::watch_id_t watch_id, uint32_t ignore_count)
Definition Target.cpp:1577
bool EnableWatchpointByID(lldb::watch_id_t watch_id)
Definition Target.cpp:1542
const lldb::ProcessSP & GetProcessSP() const
Definition Target.cpp:328
bool RemoveAllWatchpoints(bool end_to_end=true)
Definition Target.cpp:1395
bool RemoveWatchpointByID(lldb::watch_id_t watch_id)
Definition Target.cpp:1561
bool DisableAllWatchpoints(bool end_to_end=true)
Definition Target.cpp:1424
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1241
const ArchSpec & GetArchitecture() const
Definition Target.h:1283
WatchpointList & GetWatchpointList()
Definition Target.h:955
bool IgnoreAllWatchpoints(uint32_t ignore_count)
Definition Target.cpp:1506
bool DisableWatchpointByID(lldb::watch_id_t watch_id)
Definition Target.cpp:1523
lldb::WatchpointSP GetLastCreatedWatchpoint()
Definition Target.h:951
bool EnableAllWatchpoints(bool end_to_end=true)
Definition Target.cpp:1451
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:2907
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:335
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)
#define LLDB_OPT_SET_1
#define LLDB_WATCH_TYPE_WRITE
#define LLDB_OPT_SET_ALL
#define LLDB_WATCH_TYPE_MODIFY
#define LLDB_WATCH_TYPE_READ
#define UINT32_MAX
A class that represents a running process on the host machine.
std::vector< OptionArgElement > OptionElementVector
Definition Options.h:43
@ eAddressTypeLoad
Address is an address as in the current target inferior process.
@ eWatchpointIDCompletion
DescriptionLevel
Description levels for "void GetDescription(Stream *, DescriptionLevel)" calls.
@ eDescriptionLevelBrief
@ eDescriptionLevelFull
@ eDescriptionLevelVerbose
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
@ eLanguageTypeUnknown
Unknown or invalid language value.
ExpressionResults
The results of expression evaluation.
@ eExpressionCompleted
std::shared_ptr< lldb_private::Process > ProcessSP
@ eEncodingUint
unsigned integer
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
std::shared_ptr< lldb_private::Watchpoint > WatchpointSP
std::shared_ptr< lldb_private::Variable > VariableSP
@ eValueTypeVariableLocal
function local variables
uint64_t addr_t
Definition lldb-types.h:80