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