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