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