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