blob: ee4b6b9631721010edb6a6b1bd0f379782519c96 [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;
1018 uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
1019 valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0),
1020 eNoDynamicValues,
1021 expr_path_options,
1022 var_sp,
1023 error);
1024 if (valobj_sp) {
1025 AddressType addr_type;
1026 addr = valobj_sp->GetAddressOf(false, &addr_type);
1027 if (addr_type == eAddressTypeLoad) {
1028 // We're in business.
1029 // Find out the size of this variable.
1030 size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize()
1031 : m_option_watchpoint.watch_size;
1032 }
1033 } else {
1034 const char *error_cstr = error.AsCString(NULL);
1035 if (error_cstr)
1036 result.GetErrorStream().Printf("error: %s\n", error_cstr);
1037 else
1038 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n",
1039 command.GetArgumentAtIndex(0));
1040 return false;
1041 }
1042
1043 // Now it's time to create the watchpoint.
1044 uint32_t watch_type = m_option_watchpoint.watch_type;
1045 error.Clear();
1046 Watchpoint *wp = target->CreateWatchpoint(addr, size, watch_type, error).get();
1047 if (wp) {
1048 if (var_sp && var_sp->GetDeclaration().GetFile()) {
1049 StreamString ss;
1050 // True to show fullpath for declaration file.
1051 var_sp->GetDeclaration().DumpStopContext(&ss, true);
1052 wp->SetDeclInfo(ss.GetString());
1053 }
1054 StreamString ss;
1055 output_stream.Printf("Watchpoint created: ");
1056 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1057 output_stream.EOL();
1058 result.SetStatus(eReturnStatusSuccessFinishResult);
1059 } else {
1060 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n",
1061 addr, size);
1062 if (error.AsCString(NULL))
1063 result.AppendError(error.AsCString());
1064 result.SetStatus(eReturnStatusFailed);
1065 }
1066
1067 return result.Succeeded();
1068 }
1069
1070private:
1071 OptionGroupOptions m_option_group;
1072 OptionGroupWatchpoint m_option_watchpoint;
1073};
1074
1075//-------------------------------------------------------------------------
1076// CommandObjectWatchpointSetExpression
1077//-------------------------------------------------------------------------
1078#pragma mark Set
1079
1080class CommandObjectWatchpointSetExpression : public CommandObjectRaw
1081{
1082public:
1083
1084 CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) :
1085 CommandObjectRaw (interpreter,
1086 "watchpoint set expression",
1087 "Set a watchpoint on an address by supplying an expression. "
1088 "Use the '-w' option to specify the type of watchpoint and "
1089 "the '-x' option to specify the byte size to watch for. "
Johnny Chen26a24b72012-06-29 19:35:01 +00001090 "If no '-w' option is specified, it defaults to write. "
Jim Inghamda26bd22012-06-08 21:56:10 +00001091 "If no '-x' option is specified, it defaults to the target's "
1092 "pointer byte size. "
1093 "Note that there are limited hardware resources for watchpoints. "
1094 "If watchpoint setting fails, consider disable/delete existing ones "
1095 "to free up resources.",
1096 NULL,
1097 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1098 m_option_group (interpreter),
1099 m_option_watchpoint ()
1100 {
1101 SetHelpLong(
1102 "Examples: \n\
1103 \n\
1104 watchpoint set expression -w write -x 1 -- foo + 32\n\
1105 # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n");
1106
1107 CommandArgumentEntry arg;
1108 CommandArgumentData expression_arg;
1109
1110 // Define the only variant of this arg.
1111 expression_arg.arg_type = eArgTypeExpression;
1112 expression_arg.arg_repetition = eArgRepeatPlain;
1113
1114 // Push the only variant into the argument entry.
1115 arg.push_back (expression_arg);
1116
1117 // Push the data for the only argument into the m_arguments vector.
1118 m_arguments.push_back (arg);
1119
1120 // Absorb the '-w' and '-x' options into our option group.
1121 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1122 m_option_group.Finalize();
1123 }
1124
1125
1126 virtual
1127 ~CommandObjectWatchpointSetExpression () {}
1128
1129 // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString.
1130 virtual bool
1131 WantsCompletion() { return true; }
1132
1133 virtual Options *
1134 GetOptions ()
1135 {
1136 return &m_option_group;
1137 }
1138
1139protected:
1140 virtual bool
1141 DoExecute (const char *raw_command, CommandReturnObject &result)
1142 {
1143 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1144 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
1145 StackFrame *frame = exe_ctx.GetFramePtr();
1146 if (frame == NULL)
1147 {
1148 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
1149 result.SetStatus (eReturnStatusFailed);
1150 return false;
1151 }
1152
1153 Args command(raw_command);
1154
1155 // Process possible options.
1156 if (!ParseOptions (command, result))
1157 return false;
1158
1159 // If no argument is present, issue an error message. There's no way to set a watchpoint.
1160 if (command.GetArgumentCount() <= 0)
1161 {
1162 result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the addres to watch for\n");
1163 result.SetStatus(eReturnStatusFailed);
1164 return false;
1165 }
1166
1167 bool with_dash_w = m_option_watchpoint.watch_type_specified;
1168 bool with_dash_x = (m_option_watchpoint.watch_size != 0);
1169
Johnny Chen26a24b72012-06-29 19:35:01 +00001170 // If no '-w' is specified, default to '-w write'.
Jim Inghamda26bd22012-06-08 21:56:10 +00001171 if (!with_dash_w)
1172 {
Johnny Chen26a24b72012-06-29 19:35:01 +00001173 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite;
Jim Inghamda26bd22012-06-08 21:56:10 +00001174 }
1175
1176 // We passed the sanity check for the command.
1177 // Proceed to set the watchpoint now.
1178 lldb::addr_t addr = 0;
1179 size_t size = 0;
1180
1181 VariableSP var_sp;
1182 ValueObjectSP valobj_sp;
1183 Stream &output_stream = result.GetOutputStream();
1184
1185 // We will process the raw command string to rid of the '-w', '-x', or '--'
1186 llvm::StringRef raw_expr_str(raw_command);
1187 std::string expr_str = StripOptionTerminator(raw_expr_str, with_dash_w, with_dash_x).str();
1188
1189 // Sanity check for when the user forgets to terminate the option strings with a '--'.
1190 if ((with_dash_w || with_dash_w) && expr_str.empty())
1191 {
1192 result.GetErrorStream().Printf("error: did you forget to enter the option terminator string \"--\"?\n");
1193 result.SetStatus(eReturnStatusFailed);
1194 return false;
1195 }
1196
1197 // Use expression evaluation to arrive at the address to watch.
1198 const bool coerce_to_id = true;
1199 const bool unwind_on_error = true;
1200 const bool keep_in_memory = false;
1201 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
1202 frame,
1203 eExecutionPolicyOnlyWhenNeeded,
1204 coerce_to_id,
1205 unwind_on_error,
1206 keep_in_memory,
1207 eNoDynamicValues,
1208 valobj_sp);
1209 if (expr_result != eExecutionCompleted) {
1210 result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n");
1211 result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str());
1212 result.SetStatus(eReturnStatusFailed);
1213 return false;
1214 }
1215
1216 // Get the address to watch.
1217 bool success = false;
1218 addr = valobj_sp->GetValueAsUnsigned(0, &success);
1219 if (!success) {
1220 result.GetErrorStream().Printf("error: expression did not evaluate to an address\n");
1221 result.SetStatus(eReturnStatusFailed);
1222 return false;
1223 }
1224 size = with_dash_x ? m_option_watchpoint.watch_size
1225 : target->GetArchitecture().GetAddressByteSize();
1226
1227 // Now it's time to create the watchpoint.
1228 uint32_t watch_type = m_option_watchpoint.watch_type;
1229 Error error;
1230 Watchpoint *wp = target->CreateWatchpoint(addr, size, watch_type, error).get();
1231 if (wp) {
1232 if (var_sp && var_sp->GetDeclaration().GetFile()) {
1233 StreamString ss;
1234 // True to show fullpath for declaration file.
1235 var_sp->GetDeclaration().DumpStopContext(&ss, true);
1236 wp->SetDeclInfo(ss.GetString());
1237 }
1238 StreamString ss;
1239 output_stream.Printf("Watchpoint created: ");
1240 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1241 output_stream.EOL();
1242 result.SetStatus(eReturnStatusSuccessFinishResult);
1243 } else {
1244 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n",
1245 addr, size);
1246 if (error.AsCString(NULL))
1247 result.AppendError(error.AsCString());
1248 result.SetStatus(eReturnStatusFailed);
1249 }
1250
1251 return result.Succeeded();
1252 }
1253
1254private:
1255 OptionGroupOptions m_option_group;
1256 OptionGroupWatchpoint m_option_watchpoint;
1257};
1258
1259//-------------------------------------------------------------------------
1260// CommandObjectWatchpointSet
1261//-------------------------------------------------------------------------
1262#pragma mark Set
1263
1264class CommandObjectWatchpointSet : public CommandObjectMultiword
1265{
1266public:
1267
1268 CommandObjectWatchpointSet (CommandInterpreter &interpreter) :
1269 CommandObjectMultiword (interpreter,
1270 "watchpoint set",
1271 "A set of commands for setting a watchpoint.",
1272 "watchpoint set <subcommand> [<subcommand-options>]")
1273 {
1274
1275 LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter)));
1276 LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter)));
1277 }
1278
1279
1280 virtual
1281 ~CommandObjectWatchpointSet () {}
1282
1283};
1284
1285//-------------------------------------------------------------------------
Johnny Chen01acfa72011-09-22 18:04:58 +00001286// CommandObjectMultiwordWatchpoint
1287//-------------------------------------------------------------------------
1288#pragma mark MultiwordWatchpoint
1289
1290CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) :
1291 CommandObjectMultiword (interpreter,
1292 "watchpoint",
1293 "A set of commands for operating on watchpoints.",
1294 "watchpoint <command> [<command-options>]")
1295{
1296 bool status;
1297
1298 CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter));
1299 CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter));
1300 CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter));
1301 CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter));
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
1314 status = LoadSubCommand ("list", list_command_object);
1315 status = LoadSubCommand ("enable", enable_command_object);
1316 status = LoadSubCommand ("disable", disable_command_object);
1317 status = LoadSubCommand ("delete", delete_command_object);
Johnny Chene14cf4e2011-10-05 21:35:46 +00001318 status = LoadSubCommand ("ignore", ignore_command_object);
Johnny Chen712a6282011-10-17 18:58:00 +00001319 status = LoadSubCommand ("modify", modify_command_object);
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001320 status = LoadSubCommand ("set", set_command_object);
Johnny Chen01acfa72011-09-22 18:04:58 +00001321}
1322
1323CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint()
1324{
1325}
1326