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