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