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