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