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