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