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