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     { LLDB_OPT_SET_1, false, "brief",    'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
332         "Give a brief description of the watchpoint (no location info)."},
333 
334     { LLDB_OPT_SET_2, false, "full",    'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
335         "Give a full description of the watchpoint and its locations."},
336 
337     { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
338         "Explain everything we know about the watchpoint (for debugging debugger bugs)." },
339 
340     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
341 };
342 
343 //-------------------------------------------------------------------------
344 // CommandObjectWatchpointEnable
345 //-------------------------------------------------------------------------
346 #pragma mark Enable
347 
348 class CommandObjectWatchpointEnable : public CommandObjectParsed
349 {
350 public:
351     CommandObjectWatchpointEnable (CommandInterpreter &interpreter) :
352         CommandObjectParsed(interpreter,
353                             "enable",
354                             "Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.",
355                             nullptr)
356     {
357         CommandArgumentEntry arg;
358         CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
359         // Add the entry for the first argument for this command to the object's arguments vector.
360         m_arguments.push_back(arg);
361     }
362 
363     ~CommandObjectWatchpointEnable() override = default;
364 
365 protected:
366     bool
367     DoExecute (Args& command,
368              CommandReturnObject &result) override
369     {
370         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
371         if (!CheckTargetForWatchpointOperations(target, result))
372             return false;
373 
374         std::unique_lock<std::recursive_mutex> lock;
375         target->GetWatchpointList().GetListMutex(lock);
376 
377         const WatchpointList &watchpoints = target->GetWatchpointList();
378 
379         size_t num_watchpoints = watchpoints.GetSize();
380 
381         if (num_watchpoints == 0)
382         {
383             result.AppendError("No watchpoints exist to be enabled.");
384             result.SetStatus(eReturnStatusFailed);
385             return false;
386         }
387 
388         if (command.GetArgumentCount() == 0)
389         {
390             // No watchpoint selected; enable all currently set watchpoints.
391             target->EnableAllWatchpoints();
392             result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints);
393             result.SetStatus(eReturnStatusSuccessFinishNoResult);
394         }
395         else
396         {
397             // Particular watchpoints selected; enable them.
398             std::vector<uint32_t> wp_ids;
399             if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
400             {
401                 result.AppendError("Invalid watchpoints specification.");
402                 result.SetStatus(eReturnStatusFailed);
403                 return false;
404             }
405 
406             int count = 0;
407             const size_t size = wp_ids.size();
408             for (size_t i = 0; i < size; ++i)
409                 if (target->EnableWatchpointByID(wp_ids[i]))
410                     ++count;
411             result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
412             result.SetStatus(eReturnStatusSuccessFinishNoResult);
413         }
414 
415         return result.Succeeded();
416     }
417 };
418 
419 //-------------------------------------------------------------------------
420 // CommandObjectWatchpointDisable
421 //-------------------------------------------------------------------------
422 #pragma mark Disable
423 
424 class CommandObjectWatchpointDisable : public CommandObjectParsed
425 {
426 public:
427     CommandObjectWatchpointDisable (CommandInterpreter &interpreter) :
428         CommandObjectParsed(interpreter,
429                             "watchpoint disable",
430                             "Disable the specified watchpoint(s) without removing it/them.  If no watchpoints are specified, disable them all.",
431                             nullptr)
432     {
433         CommandArgumentEntry arg;
434         CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
435         // Add the entry for the first argument for this command to the object's arguments vector.
436         m_arguments.push_back(arg);
437     }
438 
439     ~CommandObjectWatchpointDisable() override = default;
440 
441 protected:
442     bool
443     DoExecute (Args& command, CommandReturnObject &result) override
444     {
445         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
446         if (!CheckTargetForWatchpointOperations(target, result))
447             return false;
448 
449         std::unique_lock<std::recursive_mutex> lock;
450         target->GetWatchpointList().GetListMutex(lock);
451 
452         const WatchpointList &watchpoints = target->GetWatchpointList();
453         size_t num_watchpoints = watchpoints.GetSize();
454 
455         if (num_watchpoints == 0)
456         {
457             result.AppendError("No watchpoints exist to be disabled.");
458             result.SetStatus(eReturnStatusFailed);
459             return false;
460         }
461 
462         if (command.GetArgumentCount() == 0)
463         {
464             // No watchpoint selected; disable all currently set watchpoints.
465             if (target->DisableAllWatchpoints())
466             {
467                 result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints);
468                 result.SetStatus(eReturnStatusSuccessFinishNoResult);
469             }
470             else
471             {
472                 result.AppendError("Disable all watchpoints failed\n");
473                 result.SetStatus(eReturnStatusFailed);
474             }
475         }
476         else
477         {
478             // Particular watchpoints selected; disable them.
479             std::vector<uint32_t> wp_ids;
480             if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
481             {
482                 result.AppendError("Invalid watchpoints specification.");
483                 result.SetStatus(eReturnStatusFailed);
484                 return false;
485             }
486 
487             int count = 0;
488             const size_t size = wp_ids.size();
489             for (size_t i = 0; i < size; ++i)
490                 if (target->DisableWatchpointByID(wp_ids[i]))
491                     ++count;
492             result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
493             result.SetStatus(eReturnStatusSuccessFinishNoResult);
494         }
495 
496         return result.Succeeded();
497     }
498 };
499 
500 //-------------------------------------------------------------------------
501 // CommandObjectWatchpointDelete
502 //-------------------------------------------------------------------------
503 #pragma mark Delete
504 
505 class CommandObjectWatchpointDelete : public CommandObjectParsed
506 {
507 public:
508     CommandObjectWatchpointDelete (CommandInterpreter &interpreter) :
509         CommandObjectParsed(interpreter,
510                             "watchpoint delete",
511                             "Delete the specified watchpoint(s).  If no watchpoints are specified, delete them all.",
512                             nullptr)
513     {
514         CommandArgumentEntry arg;
515         CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
516         // Add the entry for the first argument for this command to the object's arguments vector.
517         m_arguments.push_back(arg);
518     }
519 
520     ~CommandObjectWatchpointDelete() override = default;
521 
522 protected:
523     bool
524     DoExecute (Args& command, CommandReturnObject &result) override
525     {
526         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
527         if (!CheckTargetForWatchpointOperations(target, result))
528             return false;
529 
530         std::unique_lock<std::recursive_mutex> lock;
531         target->GetWatchpointList().GetListMutex(lock);
532 
533         const WatchpointList &watchpoints = target->GetWatchpointList();
534 
535         size_t num_watchpoints = watchpoints.GetSize();
536 
537         if (num_watchpoints == 0)
538         {
539             result.AppendError("No watchpoints exist to be deleted.");
540             result.SetStatus(eReturnStatusFailed);
541             return false;
542         }
543 
544         if (command.GetArgumentCount() == 0)
545         {
546             if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true))
547             {
548                 result.AppendMessage("Operation cancelled...");
549             }
550             else
551             {
552                 target->RemoveAllWatchpoints();
553                 result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints);
554             }
555             result.SetStatus (eReturnStatusSuccessFinishNoResult);
556         }
557         else
558         {
559             // Particular watchpoints selected; delete them.
560             std::vector<uint32_t> wp_ids;
561             if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
562             {
563                 result.AppendError("Invalid watchpoints specification.");
564                 result.SetStatus(eReturnStatusFailed);
565                 return false;
566             }
567 
568             int count = 0;
569             const size_t size = wp_ids.size();
570             for (size_t i = 0; i < size; ++i)
571                 if (target->RemoveWatchpointByID(wp_ids[i]))
572                     ++count;
573             result.AppendMessageWithFormat("%d watchpoints deleted.\n",count);
574             result.SetStatus (eReturnStatusSuccessFinishNoResult);
575         }
576 
577         return result.Succeeded();
578     }
579 };
580 
581 //-------------------------------------------------------------------------
582 // CommandObjectWatchpointIgnore
583 //-------------------------------------------------------------------------
584 
585 class CommandObjectWatchpointIgnore : public CommandObjectParsed
586 {
587 public:
588     CommandObjectWatchpointIgnore (CommandInterpreter &interpreter) :
589         CommandObjectParsed(interpreter,
590                             "watchpoint ignore",
591                             "Set ignore count on the specified watchpoint(s).  If no watchpoints are specified, set them all.",
592                             nullptr),
593         m_options()
594     {
595         CommandArgumentEntry arg;
596         CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
597         // Add the entry for the first argument for this command to the object's arguments vector.
598         m_arguments.push_back(arg);
599     }
600 
601     ~CommandObjectWatchpointIgnore() override = default;
602 
603     Options *
604     GetOptions () override
605     {
606         return &m_options;
607     }
608 
609     class CommandOptions : public Options
610     {
611     public:
612         CommandOptions() :
613             Options(),
614             m_ignore_count (0)
615         {
616         }
617 
618         ~CommandOptions() override = default;
619 
620         Error
621         SetOptionValue(uint32_t option_idx, const char *option_arg,
622                        ExecutionContext *execution_context) override
623         {
624             Error error;
625             const int short_option = m_getopt_table[option_idx].val;
626 
627             switch (short_option)
628             {
629                 case 'i':
630                     m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0);
631                     if (m_ignore_count == UINT32_MAX)
632                        error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
633                     break;
634                 default:
635                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
636                     break;
637             }
638 
639             return error;
640         }
641 
642         void
643         OptionParsingStarting(ExecutionContext *execution_context) override
644         {
645             m_ignore_count = 0;
646         }
647 
648         const OptionDefinition *
649         GetDefinitions () override
650         {
651             return g_option_table;
652         }
653 
654         // Options table: Required for subclasses of Options.
655 
656         static OptionDefinition g_option_table[];
657 
658         // Instance variables to hold the values for command options.
659 
660         uint32_t m_ignore_count;
661     };
662 
663 protected:
664     bool
665     DoExecute (Args& command,
666              CommandReturnObject &result) override
667     {
668         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
669         if (!CheckTargetForWatchpointOperations(target, result))
670             return false;
671 
672         std::unique_lock<std::recursive_mutex> lock;
673         target->GetWatchpointList().GetListMutex(lock);
674 
675         const WatchpointList &watchpoints = target->GetWatchpointList();
676 
677         size_t num_watchpoints = watchpoints.GetSize();
678 
679         if (num_watchpoints == 0)
680         {
681             result.AppendError("No watchpoints exist to be ignored.");
682             result.SetStatus(eReturnStatusFailed);
683             return false;
684         }
685 
686         if (command.GetArgumentCount() == 0)
687         {
688             target->IgnoreAllWatchpoints(m_options.m_ignore_count);
689             result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64 " watchpoints)\n", (uint64_t)num_watchpoints);
690             result.SetStatus (eReturnStatusSuccessFinishNoResult);
691         }
692         else
693         {
694             // Particular watchpoints selected; ignore them.
695             std::vector<uint32_t> wp_ids;
696             if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
697             {
698                 result.AppendError("Invalid watchpoints specification.");
699                 result.SetStatus(eReturnStatusFailed);
700                 return false;
701             }
702 
703             int count = 0;
704             const size_t size = wp_ids.size();
705             for (size_t i = 0; i < size; ++i)
706                 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
707                     ++count;
708             result.AppendMessageWithFormat("%d watchpoints ignored.\n",count);
709             result.SetStatus (eReturnStatusSuccessFinishNoResult);
710         }
711 
712         return result.Succeeded();
713     }
714 
715 private:
716     CommandOptions m_options;
717 };
718 
719 #pragma mark Ignore::CommandOptions
720 
721 OptionDefinition
722 CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] =
723 {
724     { 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." },
725     { 0,                false, nullptr,            0 , 0,                 nullptr, nullptr, 0,    eArgTypeNone, nullptr }
726 };
727 
728 //-------------------------------------------------------------------------
729 // CommandObjectWatchpointModify
730 //-------------------------------------------------------------------------
731 #pragma mark Modify
732 
733 class CommandObjectWatchpointModify : public CommandObjectParsed
734 {
735 public:
736     CommandObjectWatchpointModify (CommandInterpreter &interpreter) :
737         CommandObjectParsed(interpreter,
738                             "watchpoint modify",
739                             "Modify the options on a watchpoint or set of watchpoints in the executable.  "
740                             "If no watchpoint is specified, act on the last created watchpoint.  "
741                             "Passing an empty argument clears the modification.",
742                             nullptr),
743         m_options()
744     {
745         CommandArgumentEntry arg;
746         CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
747         // Add the entry for the first argument for this command to the object's arguments vector.
748         m_arguments.push_back (arg);
749     }
750 
751     ~CommandObjectWatchpointModify() override = default;
752 
753     Options *
754     GetOptions () override
755     {
756         return &m_options;
757     }
758 
759     class CommandOptions : public Options
760     {
761     public:
762         CommandOptions() :
763             Options(),
764             m_condition (),
765             m_condition_passed (false)
766         {
767         }
768 
769         ~CommandOptions() override = default;
770 
771         Error
772         SetOptionValue(uint32_t option_idx, const char *option_arg,
773                        ExecutionContext *execution_context) override
774         {
775             Error error;
776             const int short_option = m_getopt_table[option_idx].val;
777 
778             switch (short_option)
779             {
780                 case 'c':
781                     if (option_arg != nullptr)
782                         m_condition.assign (option_arg);
783                     else
784                         m_condition.clear();
785                     m_condition_passed = true;
786                     break;
787                 default:
788                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
789                     break;
790             }
791 
792             return error;
793         }
794 
795         void
796         OptionParsingStarting(ExecutionContext *execution_context) override
797         {
798             m_condition.clear();
799             m_condition_passed = false;
800         }
801 
802         const OptionDefinition*
803         GetDefinitions () override
804         {
805             return g_option_table;
806         }
807 
808         // Options table: Required for subclasses of Options.
809 
810         static OptionDefinition g_option_table[];
811 
812         // Instance variables to hold the values for command options.
813 
814         std::string m_condition;
815         bool m_condition_passed;
816     };
817 
818 protected:
819     bool
820     DoExecute (Args& command, CommandReturnObject &result) override
821     {
822         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
823         if (!CheckTargetForWatchpointOperations(target, result))
824             return false;
825 
826         std::unique_lock<std::recursive_mutex> lock;
827         target->GetWatchpointList().GetListMutex(lock);
828 
829         const WatchpointList &watchpoints = target->GetWatchpointList();
830 
831         size_t num_watchpoints = watchpoints.GetSize();
832 
833         if (num_watchpoints == 0)
834         {
835             result.AppendError("No watchpoints exist to be modified.");
836             result.SetStatus(eReturnStatusFailed);
837             return false;
838         }
839 
840         if (command.GetArgumentCount() == 0)
841         {
842             WatchpointSP wp_sp = target->GetLastCreatedWatchpoint();
843             wp_sp->SetCondition(m_options.m_condition.c_str());
844             result.SetStatus (eReturnStatusSuccessFinishNoResult);
845         }
846         else
847         {
848             // Particular watchpoints selected; set condition on them.
849             std::vector<uint32_t> wp_ids;
850             if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids))
851             {
852                 result.AppendError("Invalid watchpoints specification.");
853                 result.SetStatus(eReturnStatusFailed);
854                 return false;
855             }
856 
857             int count = 0;
858             const size_t size = wp_ids.size();
859             for (size_t i = 0; i < size; ++i)
860             {
861                 WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]);
862                 if (wp_sp)
863                 {
864                     wp_sp->SetCondition(m_options.m_condition.c_str());
865                     ++count;
866                 }
867             }
868             result.AppendMessageWithFormat("%d watchpoints modified.\n",count);
869             result.SetStatus (eReturnStatusSuccessFinishNoResult);
870         }
871 
872         return result.Succeeded();
873     }
874 
875 private:
876     CommandOptions m_options;
877 };
878 
879 #pragma mark Modify::CommandOptions
880 
881 OptionDefinition
882 CommandObjectWatchpointModify::CommandOptions::g_option_table[] =
883 {
884 { LLDB_OPT_SET_ALL, false, "condition",    'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
885 { 0,                false, nullptr,            0 , 0,                 nullptr, nullptr, 0,    eArgTypeNone, nullptr }
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