1 //===-- CommandObjectWatchpoint.cpp -----------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "CommandObjectWatchpoint.h"
11 #include "CommandObjectWatchpointCommand.h"
15 #include "llvm/ADT/StringRef.h"
17 #include "lldb/Breakpoint/Watchpoint.h"
18 #include "lldb/Breakpoint/WatchpointList.h"
19 #include "lldb/Core/ValueObject.h"
20 #include "lldb/Core/ValueObjectVariable.h"
21 #include "lldb/Host/OptionParser.h"
22 #include "lldb/Interpreter/CommandCompletions.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandReturnObject.h"
25 #include "lldb/Symbol/Variable.h"
26 #include "lldb/Symbol/VariableList.h"
27 #include "lldb/Target/StackFrame.h"
28 #include "lldb/Target/Target.h"
29 #include "lldb/Utility/StreamString.h"
32 using namespace lldb_private;
34 static void AddWatchpointDescription(Stream *s, Watchpoint *wp,
35 lldb::DescriptionLevel level) {
37 wp->GetDescription(s, level);
42 static bool CheckTargetForWatchpointOperations(Target *target,
43 CommandReturnObject &result) {
44 if (target == nullptr) {
45 result.AppendError("Invalid target. No existing target or watchpoints.");
46 result.SetStatus(eReturnStatusFailed);
49 bool process_is_valid =
50 target->GetProcessSP() && target->GetProcessSP()->IsAlive();
51 if (!process_is_valid) {
52 result.AppendError("Thre's no process or it is not alive.");
53 result.SetStatus(eReturnStatusFailed);
56 // Target passes our checks, return true.
60 // Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
61 static const char *RSA[4] = {"-", "to", "To", "TO"};
63 // Return the index to RSA if found; otherwise -1 is returned.
64 static int32_t WithRSAIndex(llvm::StringRef Arg) {
67 for (i = 0; i < 4; ++i)
68 if (Arg.find(RSA[i]) != llvm::StringRef::npos)
73 // Return true if wp_ids is successfully populated with the watch ids. False
75 bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
76 Target *target, Args &args, std::vector<uint32_t> &wp_ids) {
77 // Pre-condition: args.GetArgumentCount() > 0.
78 if (args.GetArgumentCount() == 0) {
79 if (target == nullptr)
81 WatchpointSP watch_sp = target->GetLastCreatedWatchpoint();
83 wp_ids.push_back(watch_sp->GetID());
89 llvm::StringRef Minus("-");
90 std::vector<llvm::StringRef> StrRefArgs;
91 llvm::StringRef first;
92 llvm::StringRef second;
95 // Go through the arguments and make a canonical form of arg list containing
96 // only numbers with possible "-" in between.
97 for (auto &entry : args.entries()) {
98 if ((idx = WithRSAIndex(entry.ref)) == -1) {
99 StrRefArgs.push_back(entry.ref);
102 // The Arg contains the range specifier, split it, then.
103 std::tie(first, second) = entry.ref.split(RSA[idx]);
105 StrRefArgs.push_back(first);
106 StrRefArgs.push_back(Minus);
108 StrRefArgs.push_back(second);
110 // Now process the canonical list and fill in the vector of uint32_t's. If
111 // there is any error, return false and the client should ignore wp_ids.
112 uint32_t beg, end, id;
113 size_t size = StrRefArgs.size();
114 bool in_range = false;
115 for (i = 0; i < size; ++i) {
116 llvm::StringRef Arg = StrRefArgs[i];
118 // Look for the 'end' of the range. Note StringRef::getAsInteger()
119 // returns true to signify error while parsing.
120 if (Arg.getAsInteger(0, end))
122 // Found a range! Now append the elements.
123 for (id = beg; id <= end; ++id)
124 wp_ids.push_back(id);
128 if (i < (size - 1) && StrRefArgs[i + 1] == Minus) {
129 if (Arg.getAsInteger(0, beg))
131 // Turn on the in_range flag, we are looking for end of range next.
136 // Otherwise, we have a simple ID. Just append it.
137 if (Arg.getAsInteger(0, beg))
139 wp_ids.push_back(beg);
142 // It is an error if after the loop, we're still in_range.
146 //-------------------------------------------------------------------------
147 // CommandObjectWatchpointList
148 //-------------------------------------------------------------------------
150 //-------------------------------------------------------------------------
151 // CommandObjectWatchpointList::Options
152 //-------------------------------------------------------------------------
153 #pragma mark List::CommandOptions
155 static constexpr OptionDefinition g_watchpoint_list_options[] = {
157 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a brief description of the watchpoint (no location info)." },
158 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Give a full description of the watchpoint and its locations." },
159 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Explain everything we know about the watchpoint (for debugging debugger bugs)." }
165 class CommandObjectWatchpointList : public CommandObjectParsed {
167 CommandObjectWatchpointList(CommandInterpreter &interpreter)
168 : CommandObjectParsed(
169 interpreter, "watchpoint list",
170 "List all watchpoints at configurable levels of detail.", nullptr),
172 CommandArgumentEntry arg;
173 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
174 eArgTypeWatchpointIDRange);
175 // Add the entry for the first argument for this command to the object's
177 m_arguments.push_back(arg);
180 ~CommandObjectWatchpointList() override = default;
182 Options *GetOptions() override { return &m_options; }
184 class CommandOptions : public Options {
188 m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to
189 // brief descriptions
192 ~CommandOptions() override = default;
194 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
195 ExecutionContext *execution_context) override {
197 const int short_option = m_getopt_table[option_idx].val;
199 switch (short_option) {
201 m_level = lldb::eDescriptionLevelBrief;
204 m_level = lldb::eDescriptionLevelFull;
207 m_level = lldb::eDescriptionLevelVerbose;
210 error.SetErrorStringWithFormat("unrecognized option '%c'",
218 void OptionParsingStarting(ExecutionContext *execution_context) override {
219 m_level = lldb::eDescriptionLevelFull;
222 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
223 return llvm::makeArrayRef(g_watchpoint_list_options);
226 // Instance variables to hold the values for command options.
228 lldb::DescriptionLevel m_level;
232 bool DoExecute(Args &command, CommandReturnObject &result) override {
233 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
234 if (target == nullptr) {
235 result.AppendError("Invalid target. No current target or watchpoints.");
236 result.SetStatus(eReturnStatusSuccessFinishNoResult);
240 if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) {
241 uint32_t num_supported_hardware_watchpoints;
242 Status error = target->GetProcessSP()->GetWatchpointSupportInfo(
243 num_supported_hardware_watchpoints);
245 result.AppendMessageWithFormat(
246 "Number of supported hardware watchpoints: %u\n",
247 num_supported_hardware_watchpoints);
250 const WatchpointList &watchpoints = target->GetWatchpointList();
252 std::unique_lock<std::recursive_mutex> lock;
253 target->GetWatchpointList().GetListMutex(lock);
255 size_t num_watchpoints = watchpoints.GetSize();
257 if (num_watchpoints == 0) {
258 result.AppendMessage("No watchpoints currently set.");
259 result.SetStatus(eReturnStatusSuccessFinishNoResult);
263 Stream &output_stream = result.GetOutputStream();
265 if (command.GetArgumentCount() == 0) {
266 // No watchpoint selected; show info about all currently set watchpoints.
267 result.AppendMessage("Current watchpoints:");
268 for (size_t i = 0; i < num_watchpoints; ++i) {
269 Watchpoint *wp = watchpoints.GetByIndex(i).get();
270 AddWatchpointDescription(&output_stream, wp, m_options.m_level);
272 result.SetStatus(eReturnStatusSuccessFinishNoResult);
274 // Particular watchpoints selected; enable them.
275 std::vector<uint32_t> wp_ids;
276 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
277 target, command, wp_ids)) {
278 result.AppendError("Invalid watchpoints specification.");
279 result.SetStatus(eReturnStatusFailed);
283 const size_t size = wp_ids.size();
284 for (size_t i = 0; i < size; ++i) {
285 Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get();
287 AddWatchpointDescription(&output_stream, wp, m_options.m_level);
288 result.SetStatus(eReturnStatusSuccessFinishNoResult);
292 return result.Succeeded();
296 CommandOptions m_options;
299 //-------------------------------------------------------------------------
300 // CommandObjectWatchpointEnable
301 //-------------------------------------------------------------------------
304 class CommandObjectWatchpointEnable : public CommandObjectParsed {
306 CommandObjectWatchpointEnable(CommandInterpreter &interpreter)
307 : CommandObjectParsed(interpreter, "enable",
308 "Enable the specified disabled watchpoint(s). If "
309 "no watchpoints are specified, enable all of them.",
311 CommandArgumentEntry arg;
312 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
313 eArgTypeWatchpointIDRange);
314 // Add the entry for the first argument for this command to the object's
316 m_arguments.push_back(arg);
319 ~CommandObjectWatchpointEnable() override = default;
322 bool DoExecute(Args &command, CommandReturnObject &result) override {
323 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
324 if (!CheckTargetForWatchpointOperations(target, result))
327 std::unique_lock<std::recursive_mutex> lock;
328 target->GetWatchpointList().GetListMutex(lock);
330 const WatchpointList &watchpoints = target->GetWatchpointList();
332 size_t num_watchpoints = watchpoints.GetSize();
334 if (num_watchpoints == 0) {
335 result.AppendError("No watchpoints exist to be enabled.");
336 result.SetStatus(eReturnStatusFailed);
340 if (command.GetArgumentCount() == 0) {
341 // No watchpoint selected; enable all currently set watchpoints.
342 target->EnableAllWatchpoints();
343 result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64
345 (uint64_t)num_watchpoints);
346 result.SetStatus(eReturnStatusSuccessFinishNoResult);
348 // Particular watchpoints selected; enable them.
349 std::vector<uint32_t> wp_ids;
350 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
351 target, command, wp_ids)) {
352 result.AppendError("Invalid watchpoints specification.");
353 result.SetStatus(eReturnStatusFailed);
358 const size_t size = wp_ids.size();
359 for (size_t i = 0; i < size; ++i)
360 if (target->EnableWatchpointByID(wp_ids[i]))
362 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
363 result.SetStatus(eReturnStatusSuccessFinishNoResult);
366 return result.Succeeded();
370 //-------------------------------------------------------------------------
371 // CommandObjectWatchpointDisable
372 //-------------------------------------------------------------------------
375 class CommandObjectWatchpointDisable : public CommandObjectParsed {
377 CommandObjectWatchpointDisable(CommandInterpreter &interpreter)
378 : CommandObjectParsed(interpreter, "watchpoint disable",
379 "Disable the specified watchpoint(s) without "
380 "removing it/them. If no watchpoints are "
381 "specified, disable them all.",
383 CommandArgumentEntry arg;
384 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
385 eArgTypeWatchpointIDRange);
386 // Add the entry for the first argument for this command to the object's
388 m_arguments.push_back(arg);
391 ~CommandObjectWatchpointDisable() override = default;
394 bool DoExecute(Args &command, CommandReturnObject &result) override {
395 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
396 if (!CheckTargetForWatchpointOperations(target, result))
399 std::unique_lock<std::recursive_mutex> lock;
400 target->GetWatchpointList().GetListMutex(lock);
402 const WatchpointList &watchpoints = target->GetWatchpointList();
403 size_t num_watchpoints = watchpoints.GetSize();
405 if (num_watchpoints == 0) {
406 result.AppendError("No watchpoints exist to be disabled.");
407 result.SetStatus(eReturnStatusFailed);
411 if (command.GetArgumentCount() == 0) {
412 // No watchpoint selected; disable all currently set watchpoints.
413 if (target->DisableAllWatchpoints()) {
414 result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64
416 (uint64_t)num_watchpoints);
417 result.SetStatus(eReturnStatusSuccessFinishNoResult);
419 result.AppendError("Disable all watchpoints failed\n");
420 result.SetStatus(eReturnStatusFailed);
423 // Particular watchpoints selected; disable them.
424 std::vector<uint32_t> wp_ids;
425 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
426 target, command, wp_ids)) {
427 result.AppendError("Invalid watchpoints specification.");
428 result.SetStatus(eReturnStatusFailed);
433 const size_t size = wp_ids.size();
434 for (size_t i = 0; i < size; ++i)
435 if (target->DisableWatchpointByID(wp_ids[i]))
437 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
438 result.SetStatus(eReturnStatusSuccessFinishNoResult);
441 return result.Succeeded();
445 //-------------------------------------------------------------------------
446 // CommandObjectWatchpointDelete
447 //-------------------------------------------------------------------------
450 class CommandObjectWatchpointDelete : public CommandObjectParsed {
452 CommandObjectWatchpointDelete(CommandInterpreter &interpreter)
453 : CommandObjectParsed(interpreter, "watchpoint delete",
454 "Delete the specified watchpoint(s). If no "
455 "watchpoints are specified, delete them all.",
457 CommandArgumentEntry arg;
458 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
459 eArgTypeWatchpointIDRange);
460 // Add the entry for the first argument for this command to the object's
462 m_arguments.push_back(arg);
465 ~CommandObjectWatchpointDelete() override = default;
468 bool DoExecute(Args &command, CommandReturnObject &result) override {
469 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
470 if (!CheckTargetForWatchpointOperations(target, result))
473 std::unique_lock<std::recursive_mutex> lock;
474 target->GetWatchpointList().GetListMutex(lock);
476 const WatchpointList &watchpoints = target->GetWatchpointList();
478 size_t num_watchpoints = watchpoints.GetSize();
480 if (num_watchpoints == 0) {
481 result.AppendError("No watchpoints exist to be deleted.");
482 result.SetStatus(eReturnStatusFailed);
486 if (command.GetArgumentCount() == 0) {
487 if (!m_interpreter.Confirm(
488 "About to delete all watchpoints, do you want to do that?",
490 result.AppendMessage("Operation cancelled...");
492 target->RemoveAllWatchpoints();
493 result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64
495 (uint64_t)num_watchpoints);
497 result.SetStatus(eReturnStatusSuccessFinishNoResult);
499 // Particular watchpoints selected; delete them.
500 std::vector<uint32_t> wp_ids;
501 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
502 target, command, wp_ids)) {
503 result.AppendError("Invalid watchpoints specification.");
504 result.SetStatus(eReturnStatusFailed);
509 const size_t size = wp_ids.size();
510 for (size_t i = 0; i < size; ++i)
511 if (target->RemoveWatchpointByID(wp_ids[i]))
513 result.AppendMessageWithFormat("%d watchpoints deleted.\n", count);
514 result.SetStatus(eReturnStatusSuccessFinishNoResult);
517 return result.Succeeded();
521 //-------------------------------------------------------------------------
522 // CommandObjectWatchpointIgnore
523 //-------------------------------------------------------------------------
525 #pragma mark Ignore::CommandOptions
526 static constexpr OptionDefinition g_watchpoint_ignore_options[] = {
528 { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }
532 class CommandObjectWatchpointIgnore : public CommandObjectParsed {
534 CommandObjectWatchpointIgnore(CommandInterpreter &interpreter)
535 : CommandObjectParsed(interpreter, "watchpoint ignore",
536 "Set ignore count on the specified watchpoint(s). "
537 "If no watchpoints are specified, set them all.",
540 CommandArgumentEntry arg;
541 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
542 eArgTypeWatchpointIDRange);
543 // Add the entry for the first argument for this command to the object's
545 m_arguments.push_back(arg);
548 ~CommandObjectWatchpointIgnore() override = default;
550 Options *GetOptions() override { return &m_options; }
552 class CommandOptions : public Options {
554 CommandOptions() : Options(), m_ignore_count(0) {}
556 ~CommandOptions() override = default;
558 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
559 ExecutionContext *execution_context) override {
561 const int short_option = m_getopt_table[option_idx].val;
563 switch (short_option) {
565 if (option_arg.getAsInteger(0, m_ignore_count))
566 error.SetErrorStringWithFormat("invalid ignore count '%s'",
567 option_arg.str().c_str());
570 error.SetErrorStringWithFormat("unrecognized option '%c'",
578 void OptionParsingStarting(ExecutionContext *execution_context) override {
582 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
583 return llvm::makeArrayRef(g_watchpoint_ignore_options);
586 // Instance variables to hold the values for command options.
588 uint32_t m_ignore_count;
592 bool DoExecute(Args &command, CommandReturnObject &result) override {
593 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
594 if (!CheckTargetForWatchpointOperations(target, result))
597 std::unique_lock<std::recursive_mutex> lock;
598 target->GetWatchpointList().GetListMutex(lock);
600 const WatchpointList &watchpoints = target->GetWatchpointList();
602 size_t num_watchpoints = watchpoints.GetSize();
604 if (num_watchpoints == 0) {
605 result.AppendError("No watchpoints exist to be ignored.");
606 result.SetStatus(eReturnStatusFailed);
610 if (command.GetArgumentCount() == 0) {
611 target->IgnoreAllWatchpoints(m_options.m_ignore_count);
612 result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64
614 (uint64_t)num_watchpoints);
615 result.SetStatus(eReturnStatusSuccessFinishNoResult);
617 // Particular watchpoints selected; ignore them.
618 std::vector<uint32_t> wp_ids;
619 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
620 target, command, wp_ids)) {
621 result.AppendError("Invalid watchpoints specification.");
622 result.SetStatus(eReturnStatusFailed);
627 const size_t size = wp_ids.size();
628 for (size_t i = 0; i < size; ++i)
629 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
631 result.AppendMessageWithFormat("%d watchpoints ignored.\n", count);
632 result.SetStatus(eReturnStatusSuccessFinishNoResult);
635 return result.Succeeded();
639 CommandOptions m_options;
642 //-------------------------------------------------------------------------
643 // CommandObjectWatchpointModify
644 //-------------------------------------------------------------------------
646 #pragma mark Modify::CommandOptions
648 static constexpr OptionDefinition g_watchpoint_modify_options[] = {
650 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true." }
656 class CommandObjectWatchpointModify : public CommandObjectParsed {
658 CommandObjectWatchpointModify(CommandInterpreter &interpreter)
659 : CommandObjectParsed(
660 interpreter, "watchpoint modify",
661 "Modify the options on a watchpoint or set of watchpoints in the "
663 "If no watchpoint is specified, act on the last created "
665 "Passing an empty argument clears the modification.",
668 CommandArgumentEntry arg;
669 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID,
670 eArgTypeWatchpointIDRange);
671 // Add the entry for the first argument for this command to the object's
673 m_arguments.push_back(arg);
676 ~CommandObjectWatchpointModify() override = default;
678 Options *GetOptions() override { return &m_options; }
680 class CommandOptions : public Options {
682 CommandOptions() : Options(), m_condition(), m_condition_passed(false) {}
684 ~CommandOptions() override = default;
686 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
687 ExecutionContext *execution_context) override {
689 const int short_option = m_getopt_table[option_idx].val;
691 switch (short_option) {
693 m_condition = option_arg;
694 m_condition_passed = true;
697 error.SetErrorStringWithFormat("unrecognized option '%c'",
705 void OptionParsingStarting(ExecutionContext *execution_context) override {
707 m_condition_passed = false;
710 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
711 return llvm::makeArrayRef(g_watchpoint_modify_options);
714 // Instance variables to hold the values for command options.
716 std::string m_condition;
717 bool m_condition_passed;
721 bool DoExecute(Args &command, CommandReturnObject &result) override {
722 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
723 if (!CheckTargetForWatchpointOperations(target, result))
726 std::unique_lock<std::recursive_mutex> lock;
727 target->GetWatchpointList().GetListMutex(lock);
729 const WatchpointList &watchpoints = target->GetWatchpointList();
731 size_t num_watchpoints = watchpoints.GetSize();
733 if (num_watchpoints == 0) {
734 result.AppendError("No watchpoints exist to be modified.");
735 result.SetStatus(eReturnStatusFailed);
739 if (command.GetArgumentCount() == 0) {
740 WatchpointSP wp_sp = target->GetLastCreatedWatchpoint();
741 wp_sp->SetCondition(m_options.m_condition.c_str());
742 result.SetStatus(eReturnStatusSuccessFinishNoResult);
744 // Particular watchpoints selected; set condition on them.
745 std::vector<uint32_t> wp_ids;
746 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(
747 target, command, wp_ids)) {
748 result.AppendError("Invalid watchpoints specification.");
749 result.SetStatus(eReturnStatusFailed);
754 const size_t size = wp_ids.size();
755 for (size_t i = 0; i < size; ++i) {
756 WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]);
758 wp_sp->SetCondition(m_options.m_condition.c_str());
762 result.AppendMessageWithFormat("%d watchpoints modified.\n", count);
763 result.SetStatus(eReturnStatusSuccessFinishNoResult);
766 return result.Succeeded();
770 CommandOptions m_options;
773 //-------------------------------------------------------------------------
774 // CommandObjectWatchpointSetVariable
775 //-------------------------------------------------------------------------
776 #pragma mark SetVariable
778 class CommandObjectWatchpointSetVariable : public CommandObjectParsed {
780 CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter)
781 : CommandObjectParsed(
782 interpreter, "watchpoint set variable",
783 "Set a watchpoint on a variable. "
784 "Use the '-w' option to specify the type of watchpoint and "
785 "the '-s' option to specify the byte size to watch for. "
786 "If no '-w' option is specified, it defaults to write. "
787 "If no '-s' option is specified, it defaults to the variable's "
789 "Note that there are limited hardware resources for watchpoints. "
790 "If watchpoint setting fails, consider disable/delete existing "
792 "to free up resources.",
794 eCommandRequiresFrame | eCommandTryTargetAPILock |
795 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
796 m_option_group(), m_option_watchpoint() {
801 (lldb) watchpoint set variable -w read_write my_global_var
804 " Watches my_global_var for read/write access, with the region to watch \
805 corresponding to the byte size of the data type.");
807 CommandArgumentEntry arg;
808 CommandArgumentData var_name_arg;
810 // Define the only variant of this arg.
811 var_name_arg.arg_type = eArgTypeVarName;
812 var_name_arg.arg_repetition = eArgRepeatPlain;
814 // Push the variant into the argument entry.
815 arg.push_back(var_name_arg);
817 // Push the data for the only argument into the m_arguments vector.
818 m_arguments.push_back(arg);
820 // Absorb the '-w' and '-s' options into our option group.
821 m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
823 m_option_group.Finalize();
826 ~CommandObjectWatchpointSetVariable() override = default;
828 Options *GetOptions() override { return &m_option_group; }
831 static size_t GetVariableCallback(void *baton, const char *name,
832 VariableList &variable_list) {
833 Target *target = static_cast<Target *>(baton);
835 return target->GetImages().FindGlobalVariables(ConstString(name),
836 UINT32_MAX, variable_list);
841 bool DoExecute(Args &command, CommandReturnObject &result) override {
842 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
843 StackFrame *frame = m_exe_ctx.GetFramePtr();
845 // If no argument is present, issue an error message. There's no way to
847 if (command.GetArgumentCount() <= 0) {
848 result.GetErrorStream().Printf("error: required argument missing; "
849 "specify your program variable to watch "
851 result.SetStatus(eReturnStatusFailed);
855 // If no '-w' is specified, default to '-w write'.
856 if (!m_option_watchpoint.watch_type_specified) {
857 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
860 // We passed the sanity check for the command. Proceed to set the
862 lldb::addr_t addr = 0;
866 ValueObjectSP valobj_sp;
867 Stream &output_stream = result.GetOutputStream();
869 // A simple watch variable gesture allows only one argument.
870 if (command.GetArgumentCount() != 1) {
871 result.GetErrorStream().Printf(
872 "error: specify exactly one variable to watch for\n");
873 result.SetStatus(eReturnStatusFailed);
877 // Things have checked out ok...
879 uint32_t expr_path_options =
880 StackFrame::eExpressionPathOptionCheckPtrVsMember |
881 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess;
882 valobj_sp = frame->GetValueForVariableExpressionPath(
883 command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options,
887 // Not in the frame; let's check the globals.
889 VariableList variable_list;
890 ValueObjectList valobj_list;
892 Status error(Variable::GetValuesForVariableExpressionPath(
893 command.GetArgumentAtIndex(0),
894 m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target,
895 variable_list, valobj_list));
897 if (valobj_list.GetSize())
898 valobj_sp = valobj_list.GetValueObjectAtIndex(0);
901 CompilerType compiler_type;
904 AddressType addr_type;
905 addr = valobj_sp->GetAddressOf(false, &addr_type);
906 if (addr_type == eAddressTypeLoad) {
907 // We're in business.
908 // Find out the size of this variable.
909 size = m_option_watchpoint.watch_size == 0
910 ? valobj_sp->GetByteSize()
911 : m_option_watchpoint.watch_size;
913 compiler_type = valobj_sp->GetCompilerType();
915 const char *error_cstr = error.AsCString(nullptr);
917 result.GetErrorStream().Printf("error: %s\n", error_cstr);
919 result.GetErrorStream().Printf("error: unable to find any variable "
920 "expression path that matches '%s'\n",
921 command.GetArgumentAtIndex(0));
925 // Now it's time to create the watchpoint.
926 uint32_t watch_type = m_option_watchpoint.watch_type;
930 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error)
933 wp->SetWatchSpec(command.GetArgumentAtIndex(0));
934 wp->SetWatchVariable(true);
935 if (var_sp && var_sp->GetDeclaration().GetFile()) {
937 // True to show fullpath for declaration file.
938 var_sp->GetDeclaration().DumpStopContext(&ss, true);
939 wp->SetDeclInfo(ss.GetString());
941 output_stream.Printf("Watchpoint created: ");
942 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
944 result.SetStatus(eReturnStatusSuccessFinishResult);
946 result.AppendErrorWithFormat(
947 "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64
948 ", variable expression='%s').\n",
949 addr, (uint64_t)size, command.GetArgumentAtIndex(0));
950 if (error.AsCString(nullptr))
951 result.AppendError(error.AsCString());
952 result.SetStatus(eReturnStatusFailed);
955 return result.Succeeded();
959 OptionGroupOptions m_option_group;
960 OptionGroupWatchpoint m_option_watchpoint;
963 //-------------------------------------------------------------------------
964 // CommandObjectWatchpointSetExpression
965 //-------------------------------------------------------------------------
968 class CommandObjectWatchpointSetExpression : public CommandObjectRaw {
970 CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter)
972 interpreter, "watchpoint set expression",
973 "Set a watchpoint on an address by supplying an expression. "
974 "Use the '-w' option to specify the type of watchpoint and "
975 "the '-s' option to specify the byte size to watch for. "
976 "If no '-w' option is specified, it defaults to write. "
977 "If no '-s' option is specified, it defaults to the target's "
978 "pointer byte size. "
979 "Note that there are limited hardware resources for watchpoints. "
980 "If watchpoint setting fails, consider disable/delete existing "
982 "to free up resources.",
984 eCommandRequiresFrame | eCommandTryTargetAPILock |
985 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
986 m_option_group(), m_option_watchpoint() {
991 (lldb) watchpoint set expression -w write -s 1 -- foo + 32
993 Watches write access for the 1-byte region pointed to by the address 'foo + 32')");
995 CommandArgumentEntry arg;
996 CommandArgumentData expression_arg;
998 // Define the only variant of this arg.
999 expression_arg.arg_type = eArgTypeExpression;
1000 expression_arg.arg_repetition = eArgRepeatPlain;
1002 // Push the only variant into the argument entry.
1003 arg.push_back(expression_arg);
1005 // Push the data for the only argument into the m_arguments vector.
1006 m_arguments.push_back(arg);
1008 // Absorb the '-w' and '-s' options into our option group.
1009 m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL,
1011 m_option_group.Finalize();
1014 ~CommandObjectWatchpointSetExpression() override = default;
1016 // Overrides base class's behavior where WantsCompletion =
1017 // !WantsRawCommandString.
1018 bool WantsCompletion() override { return true; }
1020 Options *GetOptions() override { return &m_option_group; }
1023 bool DoExecute(llvm::StringRef raw_command,
1024 CommandReturnObject &result) override {
1025 auto exe_ctx = GetCommandInterpreter().GetExecutionContext();
1026 m_option_group.NotifyOptionParsingStarting(
1027 &exe_ctx); // This is a raw command, so notify the option group
1029 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1030 StackFrame *frame = m_exe_ctx.GetFramePtr();
1032 OptionsWithRaw args(raw_command);
1034 llvm::StringRef expr = args.GetRawPart();
1037 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group,
1041 // If no argument is present, issue an error message. There's no way to
1042 // set a watchpoint.
1043 if (raw_command.trim().empty()) {
1044 result.GetErrorStream().Printf("error: required argument missing; "
1045 "specify an expression to evaulate into "
1046 "the address to watch for\n");
1047 result.SetStatus(eReturnStatusFailed);
1051 // If no '-w' is specified, default to '-w write'.
1052 if (!m_option_watchpoint.watch_type_specified) {
1053 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
1056 // We passed the sanity check for the command. Proceed to set the
1058 lldb::addr_t addr = 0;
1061 ValueObjectSP valobj_sp;
1063 // Use expression evaluation to arrive at the address to watch.
1064 EvaluateExpressionOptions options;
1065 options.SetCoerceToId(false);
1066 options.SetUnwindOnError(true);
1067 options.SetKeepInMemory(false);
1068 options.SetTryAllThreads(true);
1069 options.SetTimeout(llvm::None);
1071 ExpressionResults expr_result =
1072 target->EvaluateExpression(expr, frame, valobj_sp, options);
1073 if (expr_result != eExpressionCompleted) {
1074 result.GetErrorStream().Printf(
1075 "error: expression evaluation of address to watch failed\n");
1076 result.GetErrorStream() << "expression evaluated: \n" << expr << "\n";
1077 result.SetStatus(eReturnStatusFailed);
1081 // Get the address to watch.
1082 bool success = false;
1083 addr = valobj_sp->GetValueAsUnsigned(0, &success);
1085 result.GetErrorStream().Printf(
1086 "error: expression did not evaluate to an address\n");
1087 result.SetStatus(eReturnStatusFailed);
1091 if (m_option_watchpoint.watch_size != 0)
1092 size = m_option_watchpoint.watch_size;
1094 size = target->GetArchitecture().GetAddressByteSize();
1096 // Now it's time to create the watchpoint.
1097 uint32_t watch_type = m_option_watchpoint.watch_type;
1099 // Fetch the type from the value object, the type of the watched object is
1101 /// of the expression, so convert to that if we found a valid type.
1102 CompilerType compiler_type(valobj_sp->GetCompilerType());
1106 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error)
1109 Stream &output_stream = result.GetOutputStream();
1110 output_stream.Printf("Watchpoint created: ");
1111 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1112 output_stream.EOL();
1113 result.SetStatus(eReturnStatusSuccessFinishResult);
1115 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64
1116 ", size=%" PRIu64 ").\n",
1117 addr, (uint64_t)size);
1118 if (error.AsCString(nullptr))
1119 result.AppendError(error.AsCString());
1120 result.SetStatus(eReturnStatusFailed);
1123 return result.Succeeded();
1127 OptionGroupOptions m_option_group;
1128 OptionGroupWatchpoint m_option_watchpoint;
1131 //-------------------------------------------------------------------------
1132 // CommandObjectWatchpointSet
1133 //-------------------------------------------------------------------------
1136 class CommandObjectWatchpointSet : public CommandObjectMultiword {
1138 CommandObjectWatchpointSet(CommandInterpreter &interpreter)
1139 : CommandObjectMultiword(
1140 interpreter, "watchpoint set", "Commands for setting a watchpoint.",
1141 "watchpoint set <subcommand> [<subcommand-options>]") {
1145 CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter)));
1148 CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter)));
1151 ~CommandObjectWatchpointSet() override = default;
1154 //-------------------------------------------------------------------------
1155 // CommandObjectMultiwordWatchpoint
1156 //-------------------------------------------------------------------------
1157 #pragma mark MultiwordWatchpoint
1159 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(
1160 CommandInterpreter &interpreter)
1161 : CommandObjectMultiword(interpreter, "watchpoint",
1162 "Commands for operating on watchpoints.",
1163 "watchpoint <subcommand> [<command-options>]") {
1164 CommandObjectSP list_command_object(
1165 new CommandObjectWatchpointList(interpreter));
1166 CommandObjectSP enable_command_object(
1167 new CommandObjectWatchpointEnable(interpreter));
1168 CommandObjectSP disable_command_object(
1169 new CommandObjectWatchpointDisable(interpreter));
1170 CommandObjectSP delete_command_object(
1171 new CommandObjectWatchpointDelete(interpreter));
1172 CommandObjectSP ignore_command_object(
1173 new CommandObjectWatchpointIgnore(interpreter));
1174 CommandObjectSP command_command_object(
1175 new CommandObjectWatchpointCommand(interpreter));
1176 CommandObjectSP modify_command_object(
1177 new CommandObjectWatchpointModify(interpreter));
1178 CommandObjectSP set_command_object(
1179 new CommandObjectWatchpointSet(interpreter));
1181 list_command_object->SetCommandName("watchpoint list");
1182 enable_command_object->SetCommandName("watchpoint enable");
1183 disable_command_object->SetCommandName("watchpoint disable");
1184 delete_command_object->SetCommandName("watchpoint delete");
1185 ignore_command_object->SetCommandName("watchpoint ignore");
1186 command_command_object->SetCommandName("watchpoint command");
1187 modify_command_object->SetCommandName("watchpoint modify");
1188 set_command_object->SetCommandName("watchpoint set");
1190 LoadSubCommand("list", list_command_object);
1191 LoadSubCommand("enable", enable_command_object);
1192 LoadSubCommand("disable", disable_command_object);
1193 LoadSubCommand("delete", delete_command_object);
1194 LoadSubCommand("ignore", ignore_command_object);
1195 LoadSubCommand("command", command_command_object);
1196 LoadSubCommand("modify", modify_command_object);
1197 LoadSubCommand("set", set_command_object);
1200 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default;