blob: 591b8ec4201d81db21df75a7e85bbe12c35af319 [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
Johnny Chen1e0e73a2012-06-04 20:08:23 +000062static void
63CheckIfWatchpointsExhausted(Target *target, CommandReturnObject &result)
64{
65 uint32_t num_supported_hardware_watchpoints;
66 Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints);
67 if (error.Success())
68 {
69 uint32_t num_current_watchpoints = target->GetWatchpointList().GetSize();
70 if (num_current_watchpoints >= num_supported_hardware_watchpoints)
71 result.AppendErrorWithFormat("Number of supported hardware watchpoints (%u) has been reached.\n",
72 num_supported_hardware_watchpoints);
73 }
74}
75
Johnny Chen01acfa72011-09-22 18:04:58 +000076#include "llvm/ADT/StringRef.h"
77
78// Equivalent class: {"-", "to", "To", "TO"} of range specifier array.
79static const char* RSA[4] = { "-", "to", "To", "TO" };
80
81// Return the index to RSA if found; otherwise -1 is returned.
82static int32_t
83WithRSAIndex(llvm::StringRef &Arg)
84{
85
86 uint32_t i;
87 for (i = 0; i < 4; ++i)
88 if (Arg.find(RSA[i]) != llvm::StringRef::npos)
89 return i;
90 return -1;
91}
92
93// Return true if wp_ids is successfully populated with the watch ids.
94// False otherwise.
95static bool
96VerifyWatchpointIDs(Args &args, std::vector<uint32_t> &wp_ids)
97{
98 // Pre-condition: args.GetArgumentCount() > 0.
99 assert(args.GetArgumentCount() > 0);
100
101 llvm::StringRef Minus("-");
102 std::vector<llvm::StringRef> StrRefArgs;
103 std::pair<llvm::StringRef, llvm::StringRef> Pair;
104 size_t i;
105 int32_t idx;
106 // Go through the argments and make a canonical form of arg list containing
107 // only numbers with possible "-" in between.
108 for (i = 0; i < args.GetArgumentCount(); ++i) {
109 llvm::StringRef Arg(args.GetArgumentAtIndex(i));
110 if ((idx = WithRSAIndex(Arg)) == -1) {
111 StrRefArgs.push_back(Arg);
112 continue;
113 }
114 // The Arg contains the range specifier, split it, then.
115 Pair = Arg.split(RSA[idx]);
116 if (!Pair.first.empty())
117 StrRefArgs.push_back(Pair.first);
118 StrRefArgs.push_back(Minus);
119 if (!Pair.second.empty())
120 StrRefArgs.push_back(Pair.second);
121 }
122 // Now process the canonical list and fill in the vector of uint32_t's.
123 // If there is any error, return false and the client should ignore wp_ids.
124 uint32_t beg, end, id;
125 size_t size = StrRefArgs.size();
126 bool in_range = false;
127 for (i = 0; i < size; ++i) {
128 llvm::StringRef Arg = StrRefArgs[i];
129 if (in_range) {
130 // Look for the 'end' of the range. Note StringRef::getAsInteger()
131 // returns true to signify error while parsing.
132 if (Arg.getAsInteger(0, end))
133 return false;
134 // Found a range! Now append the elements.
135 for (id = beg; id <= end; ++id)
136 wp_ids.push_back(id);
137 in_range = false;
138 continue;
139 }
140 if (i < (size - 1) && StrRefArgs[i+1] == Minus) {
141 if (Arg.getAsInteger(0, beg))
142 return false;
143 // Turn on the in_range flag, we are looking for end of range next.
144 ++i; in_range = true;
145 continue;
146 }
147 // Otherwise, we have a simple ID. Just append it.
148 if (Arg.getAsInteger(0, beg))
149 return false;
150 wp_ids.push_back(beg);
151 }
152 // It is an error if after the loop, we're still in_range.
153 if (in_range)
154 return false;
155
156 return true; // Success!
157}
158
159//-------------------------------------------------------------------------
160// CommandObjectMultiwordWatchpoint
161//-------------------------------------------------------------------------
162#pragma mark MultiwordWatchpoint
163
164CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) :
165 CommandObjectMultiword (interpreter,
166 "watchpoint",
167 "A set of commands for operating on watchpoints.",
168 "watchpoint <command> [<command-options>]")
169{
170 bool status;
171
172 CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter));
173 CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter));
174 CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter));
175 CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter));
Johnny Chene14cf4e2011-10-05 21:35:46 +0000176 CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter));
Johnny Chen712a6282011-10-17 18:58:00 +0000177 CommandObjectSP modify_command_object (new CommandObjectWatchpointModify (interpreter));
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000178 CommandObjectSP set_command_object (new CommandObjectWatchpointSet (interpreter));
Johnny Chen01acfa72011-09-22 18:04:58 +0000179
180 list_command_object->SetCommandName ("watchpoint list");
181 enable_command_object->SetCommandName("watchpoint enable");
182 disable_command_object->SetCommandName("watchpoint disable");
183 delete_command_object->SetCommandName("watchpoint delete");
Johnny Chene14cf4e2011-10-05 21:35:46 +0000184 ignore_command_object->SetCommandName("watchpoint ignore");
Johnny Chen712a6282011-10-17 18:58:00 +0000185 modify_command_object->SetCommandName("watchpoint modify");
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000186 set_command_object->SetCommandName("watchpoint set");
Johnny Chen01acfa72011-09-22 18:04:58 +0000187
188 status = LoadSubCommand ("list", list_command_object);
189 status = LoadSubCommand ("enable", enable_command_object);
190 status = LoadSubCommand ("disable", disable_command_object);
191 status = LoadSubCommand ("delete", delete_command_object);
Johnny Chene14cf4e2011-10-05 21:35:46 +0000192 status = LoadSubCommand ("ignore", ignore_command_object);
Johnny Chen712a6282011-10-17 18:58:00 +0000193 status = LoadSubCommand ("modify", modify_command_object);
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000194 status = LoadSubCommand ("set", set_command_object);
Johnny Chen01acfa72011-09-22 18:04:58 +0000195}
196
197CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint()
198{
199}
200
201//-------------------------------------------------------------------------
202// CommandObjectWatchpointList::Options
203//-------------------------------------------------------------------------
204#pragma mark List::CommandOptions
205
206CommandObjectWatchpointList::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
207 Options(interpreter),
208 m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions
209{
210}
211
212CommandObjectWatchpointList::CommandOptions::~CommandOptions()
213{
214}
215
216OptionDefinition
217CommandObjectWatchpointList::CommandOptions::g_option_table[] =
218{
219 { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone,
220 "Give a brief description of the watchpoint (no location info)."},
221
222 { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, eArgTypeNone,
223 "Give a full description of the watchpoint and its locations."},
224
225 { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone,
226 "Explain everything we know about the watchpoint (for debugging debugger bugs)." },
227
228 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
229};
230
231const OptionDefinition*
232CommandObjectWatchpointList::CommandOptions::GetDefinitions()
233{
234 return g_option_table;
235}
236
237Error
238CommandObjectWatchpointList::CommandOptions::SetOptionValue(uint32_t option_idx, const char *option_arg)
239{
240 Error error;
241 char short_option = (char) m_getopt_table[option_idx].val;
242
243 switch (short_option)
244 {
245 case 'b':
246 m_level = lldb::eDescriptionLevelBrief;
247 break;
248 case 'f':
249 m_level = lldb::eDescriptionLevelFull;
250 break;
251 case 'v':
252 m_level = lldb::eDescriptionLevelVerbose;
253 break;
254 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000255 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
Johnny Chen01acfa72011-09-22 18:04:58 +0000256 break;
257 }
258
259 return error;
260}
261
262void
263CommandObjectWatchpointList::CommandOptions::OptionParsingStarting()
264{
265 m_level = lldb::eDescriptionLevelFull;
266}
267
268//-------------------------------------------------------------------------
269// CommandObjectWatchpointList
270//-------------------------------------------------------------------------
271#pragma mark List
272
273CommandObjectWatchpointList::CommandObjectWatchpointList(CommandInterpreter &interpreter) :
274 CommandObject(interpreter,
275 "watchpoint list",
276 "List all watchpoints at configurable levels of detail.",
277 NULL),
278 m_options(interpreter)
279{
280 CommandArgumentEntry arg;
Johnny Chencacedfb2011-09-22 22:34:09 +0000281 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
Johnny Chen01acfa72011-09-22 18:04:58 +0000282 // Add the entry for the first argument for this command to the object's arguments vector.
283 m_arguments.push_back(arg);
284}
285
286CommandObjectWatchpointList::~CommandObjectWatchpointList()
287{
288}
289
290Options *
291CommandObjectWatchpointList::GetOptions()
292{
293 return &m_options;
294}
295
296bool
297CommandObjectWatchpointList::Execute(Args& args, CommandReturnObject &result)
298{
299 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
300 if (target == NULL)
301 {
302 result.AppendError ("Invalid target. No current target or watchpoints.");
303 result.SetStatus (eReturnStatusSuccessFinishNoResult);
304 return true;
305 }
306
Johnny Chen7cbdcfb2012-05-23 21:09:52 +0000307 if (target->GetProcessSP() && target->GetProcessSP()->IsAlive())
308 {
309 uint32_t num_supported_hardware_watchpoints;
310 Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints);
311 if (error.Success())
312 result.AppendMessageWithFormat("Number of supported hardware watchpoints: %u\n",
313 num_supported_hardware_watchpoints);
314 }
315
Johnny Chenecd4feb2011-10-14 00:42:25 +0000316 const WatchpointList &watchpoints = target->GetWatchpointList();
Johnny Chen01acfa72011-09-22 18:04:58 +0000317 Mutex::Locker locker;
Johnny Chenecd4feb2011-10-14 00:42:25 +0000318 target->GetWatchpointList().GetListMutex(locker);
Johnny Chen01acfa72011-09-22 18:04:58 +0000319
320 size_t num_watchpoints = watchpoints.GetSize();
321
322 if (num_watchpoints == 0)
323 {
324 result.AppendMessage("No watchpoints currently set.");
325 result.SetStatus(eReturnStatusSuccessFinishNoResult);
326 return true;
327 }
328
329 Stream &output_stream = result.GetOutputStream();
330
331 if (args.GetArgumentCount() == 0)
332 {
333 // No watchpoint selected; show info about all currently set watchpoints.
334 result.AppendMessage ("Current watchpoints:");
335 for (size_t i = 0; i < num_watchpoints; ++i)
336 {
Johnny Chenecd4feb2011-10-14 00:42:25 +0000337 Watchpoint *wp = watchpoints.GetByIndex(i).get();
338 AddWatchpointDescription(&output_stream, wp, m_options.m_level);
Johnny Chen01acfa72011-09-22 18:04:58 +0000339 }
340 result.SetStatus(eReturnStatusSuccessFinishNoResult);
341 }
342 else
343 {
344 // Particular watchpoints selected; enable them.
345 std::vector<uint32_t> wp_ids;
346 if (!VerifyWatchpointIDs(args, wp_ids))
347 {
348 result.AppendError("Invalid watchpoints specification.");
349 result.SetStatus(eReturnStatusFailed);
350 return false;
351 }
352
353 const size_t size = wp_ids.size();
354 for (size_t i = 0; i < size; ++i)
355 {
Johnny Chenecd4feb2011-10-14 00:42:25 +0000356 Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get();
357 if (wp)
358 AddWatchpointDescription(&output_stream, wp, m_options.m_level);
Johnny Chen01acfa72011-09-22 18:04:58 +0000359 result.SetStatus(eReturnStatusSuccessFinishNoResult);
360 }
361 }
362
363 return result.Succeeded();
364}
365
366//-------------------------------------------------------------------------
367// CommandObjectWatchpointEnable
368//-------------------------------------------------------------------------
369#pragma mark Enable
370
371CommandObjectWatchpointEnable::CommandObjectWatchpointEnable(CommandInterpreter &interpreter) :
372 CommandObject(interpreter,
373 "enable",
374 "Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.",
375 NULL)
376{
377 CommandArgumentEntry arg;
Johnny Chencacedfb2011-09-22 22:34:09 +0000378 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
Johnny Chen01acfa72011-09-22 18:04:58 +0000379 // Add the entry for the first argument for this command to the object's arguments vector.
380 m_arguments.push_back(arg);
381}
382
383CommandObjectWatchpointEnable::~CommandObjectWatchpointEnable()
384{
385}
386
387bool
388CommandObjectWatchpointEnable::Execute(Args& args, CommandReturnObject &result)
389{
390 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
391 if (!CheckTargetForWatchpointOperations(target, result))
392 return false;
393
394 Mutex::Locker locker;
Johnny Chenecd4feb2011-10-14 00:42:25 +0000395 target->GetWatchpointList().GetListMutex(locker);
Johnny Chen01acfa72011-09-22 18:04:58 +0000396
Johnny Chenecd4feb2011-10-14 00:42:25 +0000397 const WatchpointList &watchpoints = target->GetWatchpointList();
Johnny Chen01acfa72011-09-22 18:04:58 +0000398
399 size_t num_watchpoints = watchpoints.GetSize();
400
401 if (num_watchpoints == 0)
402 {
403 result.AppendError("No watchpoints exist to be enabled.");
404 result.SetStatus(eReturnStatusFailed);
405 return false;
406 }
407
408 if (args.GetArgumentCount() == 0)
409 {
410 // No watchpoint selected; enable all currently set watchpoints.
Johnny Chenecd4feb2011-10-14 00:42:25 +0000411 target->EnableAllWatchpoints();
Johnny Chen01acfa72011-09-22 18:04:58 +0000412 result.AppendMessageWithFormat("All watchpoints enabled. (%lu watchpoints)\n", num_watchpoints);
413 result.SetStatus(eReturnStatusSuccessFinishNoResult);
414 }
415 else
416 {
417 // Particular watchpoints selected; enable them.
418 std::vector<uint32_t> wp_ids;
419 if (!VerifyWatchpointIDs(args, wp_ids))
420 {
421 result.AppendError("Invalid watchpoints specification.");
422 result.SetStatus(eReturnStatusFailed);
423 return false;
424 }
425
426 int count = 0;
427 const size_t size = wp_ids.size();
428 for (size_t i = 0; i < size; ++i)
Johnny Chenecd4feb2011-10-14 00:42:25 +0000429 if (target->EnableWatchpointByID(wp_ids[i]))
Johnny Chen01acfa72011-09-22 18:04:58 +0000430 ++count;
431 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count);
432 result.SetStatus(eReturnStatusSuccessFinishNoResult);
433 }
434
435 return result.Succeeded();
436}
437
438//-------------------------------------------------------------------------
439// CommandObjectWatchpointDisable
440//-------------------------------------------------------------------------
441#pragma mark Disable
442
443CommandObjectWatchpointDisable::CommandObjectWatchpointDisable(CommandInterpreter &interpreter) :
444 CommandObject(interpreter,
445 "watchpoint disable",
446 "Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all.",
447 NULL)
448{
449 CommandArgumentEntry arg;
Johnny Chencacedfb2011-09-22 22:34:09 +0000450 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
Johnny Chen01acfa72011-09-22 18:04:58 +0000451 // Add the entry for the first argument for this command to the object's arguments vector.
452 m_arguments.push_back(arg);
453}
454
455CommandObjectWatchpointDisable::~CommandObjectWatchpointDisable()
456{
457}
458
459bool
460CommandObjectWatchpointDisable::Execute(Args& args, CommandReturnObject &result)
461{
462 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
463 if (!CheckTargetForWatchpointOperations(target, result))
464 return false;
465
466 Mutex::Locker locker;
Johnny Chenecd4feb2011-10-14 00:42:25 +0000467 target->GetWatchpointList().GetListMutex(locker);
Johnny Chen01acfa72011-09-22 18:04:58 +0000468
Johnny Chenecd4feb2011-10-14 00:42:25 +0000469 const WatchpointList &watchpoints = target->GetWatchpointList();
Johnny Chen01acfa72011-09-22 18:04:58 +0000470 size_t num_watchpoints = watchpoints.GetSize();
471
472 if (num_watchpoints == 0)
473 {
474 result.AppendError("No watchpoints exist to be disabled.");
475 result.SetStatus(eReturnStatusFailed);
476 return false;
477 }
478
479 if (args.GetArgumentCount() == 0)
480 {
481 // No watchpoint selected; disable all currently set watchpoints.
Johnny Chenecd4feb2011-10-14 00:42:25 +0000482 if (target->DisableAllWatchpoints())
Johnny Chen01acfa72011-09-22 18:04:58 +0000483 {
484 result.AppendMessageWithFormat("All watchpoints disabled. (%lu watchpoints)\n", num_watchpoints);
485 result.SetStatus(eReturnStatusSuccessFinishNoResult);
486 }
487 else
488 {
489 result.AppendError("Disable all watchpoints failed\n");
490 result.SetStatus(eReturnStatusFailed);
491 }
492 }
493 else
494 {
495 // Particular watchpoints selected; disable them.
496 std::vector<uint32_t> wp_ids;
497 if (!VerifyWatchpointIDs(args, wp_ids))
498 {
499 result.AppendError("Invalid watchpoints specification.");
500 result.SetStatus(eReturnStatusFailed);
501 return false;
502 }
503
504 int count = 0;
505 const size_t size = wp_ids.size();
506 for (size_t i = 0; i < size; ++i)
Johnny Chenecd4feb2011-10-14 00:42:25 +0000507 if (target->DisableWatchpointByID(wp_ids[i]))
Johnny Chen01acfa72011-09-22 18:04:58 +0000508 ++count;
509 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count);
510 result.SetStatus(eReturnStatusSuccessFinishNoResult);
511 }
512
513 return result.Succeeded();
514}
515
516//-------------------------------------------------------------------------
517// CommandObjectWatchpointDelete
518//-------------------------------------------------------------------------
519#pragma mark Delete
520
521CommandObjectWatchpointDelete::CommandObjectWatchpointDelete(CommandInterpreter &interpreter) :
522 CommandObject(interpreter,
523 "watchpoint delete",
524 "Delete the specified watchpoint(s). If no watchpoints are specified, delete them all.",
525 NULL)
526{
527 CommandArgumentEntry arg;
Johnny Chencacedfb2011-09-22 22:34:09 +0000528 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
Johnny Chen01acfa72011-09-22 18:04:58 +0000529 // Add the entry for the first argument for this command to the object's arguments vector.
530 m_arguments.push_back(arg);
531}
532
533CommandObjectWatchpointDelete::~CommandObjectWatchpointDelete()
534{
535}
536
537bool
538CommandObjectWatchpointDelete::Execute(Args& args, CommandReturnObject &result)
539{
540 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
541 if (!CheckTargetForWatchpointOperations(target, result))
542 return false;
543
544 Mutex::Locker locker;
Johnny Chenecd4feb2011-10-14 00:42:25 +0000545 target->GetWatchpointList().GetListMutex(locker);
Johnny Chen01acfa72011-09-22 18:04:58 +0000546
Johnny Chenecd4feb2011-10-14 00:42:25 +0000547 const WatchpointList &watchpoints = target->GetWatchpointList();
Johnny Chen01acfa72011-09-22 18:04:58 +0000548
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 (args.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 {
Johnny Chenecd4feb2011-10-14 00:42:25 +0000566 target->RemoveAllWatchpoints();
Johnny Chen01acfa72011-09-22 18:04:58 +0000567 result.AppendMessageWithFormat("All watchpoints removed. (%lu watchpoints)\n", num_watchpoints);
568 }
569 result.SetStatus (eReturnStatusSuccessFinishNoResult);
570 }
571 else
572 {
573 // Particular watchpoints selected; delete them.
574 std::vector<uint32_t> wp_ids;
575 if (!VerifyWatchpointIDs(args, wp_ids))
576 {
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)
Johnny Chenecd4feb2011-10-14 00:42:25 +0000585 if (target->RemoveWatchpointByID(wp_ids[i]))
Johnny Chen01acfa72011-09-22 18:04:58 +0000586 ++count;
587 result.AppendMessageWithFormat("%d watchpoints deleted.\n",count);
588 result.SetStatus (eReturnStatusSuccessFinishNoResult);
589 }
590
591 return result.Succeeded();
592}
593
Johnny Chene14cf4e2011-10-05 21:35:46 +0000594//-------------------------------------------------------------------------
595// CommandObjectWatchpointIgnore::CommandOptions
596//-------------------------------------------------------------------------
597#pragma mark Ignore::CommandOptions
598
599CommandObjectWatchpointIgnore::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
600 Options (interpreter),
601 m_ignore_count (0)
602{
603}
604
605CommandObjectWatchpointIgnore::CommandOptions::~CommandOptions ()
606{
607}
608
609OptionDefinition
610CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] =
611{
612 { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, NULL, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." },
613 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
614};
615
616const OptionDefinition*
617CommandObjectWatchpointIgnore::CommandOptions::GetDefinitions ()
618{
619 return g_option_table;
620}
621
622Error
623CommandObjectWatchpointIgnore::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
624{
625 Error error;
626 char short_option = (char) m_getopt_table[option_idx].val;
627
628 switch (short_option)
629 {
630 case 'i':
631 {
632 m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0);
633 if (m_ignore_count == UINT32_MAX)
Greg Clayton9c236732011-10-26 00:56:27 +0000634 error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg);
Johnny Chene14cf4e2011-10-05 21:35:46 +0000635 }
636 break;
637 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000638 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Johnny Chene14cf4e2011-10-05 21:35:46 +0000639 break;
640 }
641
642 return error;
643}
644
645void
646CommandObjectWatchpointIgnore::CommandOptions::OptionParsingStarting ()
647{
648 m_ignore_count = 0;
649}
650
651//-------------------------------------------------------------------------
652// CommandObjectWatchpointIgnore
653//-------------------------------------------------------------------------
654#pragma mark Ignore
655
656CommandObjectWatchpointIgnore::CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) :
657 CommandObject(interpreter,
658 "watchpoint ignore",
659 "Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all.",
660 NULL),
661 m_options (interpreter)
662{
663 CommandArgumentEntry arg;
664 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
665 // Add the entry for the first argument for this command to the object's arguments vector.
666 m_arguments.push_back(arg);
667}
668
669CommandObjectWatchpointIgnore::~CommandObjectWatchpointIgnore()
670{
671}
672
673Options *
674CommandObjectWatchpointIgnore::GetOptions ()
675{
676 return &m_options;
677}
678
679bool
680CommandObjectWatchpointIgnore::Execute(Args& args, CommandReturnObject &result)
681{
682 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
683 if (!CheckTargetForWatchpointOperations(target, result))
684 return false;
685
686 Mutex::Locker locker;
Johnny Chenecd4feb2011-10-14 00:42:25 +0000687 target->GetWatchpointList().GetListMutex(locker);
Johnny Chene14cf4e2011-10-05 21:35:46 +0000688
Johnny Chenecd4feb2011-10-14 00:42:25 +0000689 const WatchpointList &watchpoints = target->GetWatchpointList();
Johnny Chene14cf4e2011-10-05 21:35:46 +0000690
691 size_t num_watchpoints = watchpoints.GetSize();
692
693 if (num_watchpoints == 0)
694 {
695 result.AppendError("No watchpoints exist to be ignored.");
696 result.SetStatus(eReturnStatusFailed);
697 return false;
698 }
699
700 if (args.GetArgumentCount() == 0)
701 {
Johnny Chenecd4feb2011-10-14 00:42:25 +0000702 target->IgnoreAllWatchpoints(m_options.m_ignore_count);
Johnny Chene14cf4e2011-10-05 21:35:46 +0000703 result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints);
704 result.SetStatus (eReturnStatusSuccessFinishNoResult);
705 }
706 else
707 {
708 // Particular watchpoints selected; ignore them.
709 std::vector<uint32_t> wp_ids;
710 if (!VerifyWatchpointIDs(args, wp_ids))
711 {
712 result.AppendError("Invalid watchpoints specification.");
713 result.SetStatus(eReturnStatusFailed);
714 return false;
715 }
716
717 int count = 0;
718 const size_t size = wp_ids.size();
719 for (size_t i = 0; i < size; ++i)
Johnny Chenecd4feb2011-10-14 00:42:25 +0000720 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count))
Johnny Chene14cf4e2011-10-05 21:35:46 +0000721 ++count;
722 result.AppendMessageWithFormat("%d watchpoints ignored.\n",count);
723 result.SetStatus (eReturnStatusSuccessFinishNoResult);
724 }
725
726 return result.Succeeded();
727}
728
Johnny Chen712a6282011-10-17 18:58:00 +0000729//-------------------------------------------------------------------------
730// CommandObjectWatchpointModify::CommandOptions
731//-------------------------------------------------------------------------
732#pragma mark Modify::CommandOptions
733
734CommandObjectWatchpointModify::CommandOptions::CommandOptions(CommandInterpreter &interpreter) :
735 Options (interpreter),
736 m_condition (),
737 m_condition_passed (false)
738{
739}
740
741CommandObjectWatchpointModify::CommandOptions::~CommandOptions ()
742{
743}
744
745OptionDefinition
746CommandObjectWatchpointModify::CommandOptions::g_option_table[] =
747{
748{ LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, NULL, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."},
749{ 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
750};
751
752const OptionDefinition*
753CommandObjectWatchpointModify::CommandOptions::GetDefinitions ()
754{
755 return g_option_table;
756}
757
758Error
759CommandObjectWatchpointModify::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg)
760{
761 Error error;
762 char short_option = (char) m_getopt_table[option_idx].val;
763
764 switch (short_option)
765 {
766 case 'c':
767 if (option_arg != NULL)
768 m_condition.assign (option_arg);
769 else
770 m_condition.clear();
771 m_condition_passed = true;
772 break;
773 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000774 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
Johnny Chen712a6282011-10-17 18:58:00 +0000775 break;
776 }
777
778 return error;
779}
780
781void
782CommandObjectWatchpointModify::CommandOptions::OptionParsingStarting ()
783{
784 m_condition.clear();
785 m_condition_passed = false;
786}
787
788//-------------------------------------------------------------------------
789// CommandObjectWatchpointModify
790//-------------------------------------------------------------------------
791#pragma mark Modify
792
793CommandObjectWatchpointModify::CommandObjectWatchpointModify (CommandInterpreter &interpreter) :
794 CommandObject (interpreter,
795 "watchpoint modify",
796 "Modify the options on a watchpoint or set of watchpoints in the executable. "
797 "If no watchpoint is specified, act on the last created watchpoint. "
798 "Passing an empty argument clears the modification.",
799 NULL),
800 m_options (interpreter)
801{
802 CommandArgumentEntry arg;
803 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange);
804 // Add the entry for the first argument for this command to the object's arguments vector.
805 m_arguments.push_back (arg);
806}
807
808CommandObjectWatchpointModify::~CommandObjectWatchpointModify ()
809{
810}
811
812Options *
813CommandObjectWatchpointModify::GetOptions ()
814{
815 return &m_options;
816}
817
818bool
819CommandObjectWatchpointModify::Execute
820(
821 Args& args,
822 CommandReturnObject &result
823)
824{
825 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
826 if (!CheckTargetForWatchpointOperations(target, result))
827 return false;
828
829 Mutex::Locker locker;
830 target->GetWatchpointList().GetListMutex(locker);
831
832 const WatchpointList &watchpoints = target->GetWatchpointList();
833
834 size_t num_watchpoints = watchpoints.GetSize();
835
836 if (num_watchpoints == 0)
837 {
838 result.AppendError("No watchpoints exist to be modified.");
839 result.SetStatus(eReturnStatusFailed);
840 return false;
841 }
842
843 if (args.GetArgumentCount() == 0)
844 {
845 WatchpointSP wp_sp = target->GetLastCreatedWatchpoint();
846 wp_sp->SetCondition(m_options.m_condition.c_str());
847 result.SetStatus (eReturnStatusSuccessFinishNoResult);
848 }
849 else
850 {
851 // Particular watchpoints selected; set condition on them.
852 std::vector<uint32_t> wp_ids;
853 if (!VerifyWatchpointIDs(args, wp_ids))
854 {
855 result.AppendError("Invalid watchpoints specification.");
856 result.SetStatus(eReturnStatusFailed);
857 return false;
858 }
859
860 int count = 0;
861 const size_t size = wp_ids.size();
862 for (size_t i = 0; i < size; ++i)
863 {
864 WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]);
865 if (wp_sp)
866 {
867 wp_sp->SetCondition(m_options.m_condition.c_str());
868 ++count;
869 }
870 }
871 result.AppendMessageWithFormat("%d watchpoints modified.\n",count);
872 result.SetStatus (eReturnStatusSuccessFinishNoResult);
873 }
874
875 return result.Succeeded();
876}
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000877
878//-------------------------------------------------------------------------
879// CommandObjectWatchpointSet
880//-------------------------------------------------------------------------
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000881
882CommandObjectWatchpointSet::CommandObjectWatchpointSet (CommandInterpreter &interpreter) :
Johnny Chen42404d22012-02-08 22:37:48 +0000883 CommandObjectMultiword (interpreter,
884 "watchpoint set",
885 "A set of commands for setting a watchpoint.",
886 "watchpoint set <subcommand> [<subcommand-options>]")
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000887{
Johnny Chen42404d22012-02-08 22:37:48 +0000888
889 LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter)));
890 LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter)));
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000891}
892
893CommandObjectWatchpointSet::~CommandObjectWatchpointSet ()
894{
895}
896
Johnny Chen42404d22012-02-08 22:37:48 +0000897//-------------------------------------------------------------------------
898// CommandObjectWatchpointSetVariable
899//-------------------------------------------------------------------------
900#pragma mark Set
901
902CommandObjectWatchpointSetVariable::CommandObjectWatchpointSetVariable (CommandInterpreter &interpreter) :
903 CommandObject (interpreter,
904 "watchpoint set variable",
905 "Set a watchpoint on a variable. "
906 "Use the '-w' option to specify the type of watchpoint and "
907 "the '-x' option to specify the byte size to watch for. "
908 "If no '-w' option is specified, it defaults to read_write. "
909 "If no '-x' option is specified, it defaults to the variable's "
910 "byte size. "
Johnny Chen5564b582012-04-27 05:27:07 +0000911 "Note that there are limited hardware resources for watchpoints. "
912 "If watchpoint setting fails, consider disable/delete existing ones "
913 "to free up resources.",
Johnny Chen42404d22012-02-08 22:37:48 +0000914 NULL,
915 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
916 m_option_group (interpreter),
917 m_option_watchpoint ()
918{
919 SetHelpLong(
920"Examples: \n\
921\n\
922 watchpoint set variable -w read_wriate my_global_var \n\
923 # Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n");
924
925 CommandArgumentEntry arg;
926 CommandArgumentData var_name_arg;
927
928 // Define the only variant of this arg.
929 var_name_arg.arg_type = eArgTypeVarName;
930 var_name_arg.arg_repetition = eArgRepeatPlain;
931
932 // Push the variant into the argument entry.
933 arg.push_back (var_name_arg);
934
935 // Push the data for the only argument into the m_arguments vector.
936 m_arguments.push_back (arg);
937
938 // Absorb the '-w' and '-x' options into our option group.
939 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
940 m_option_group.Finalize();
941}
942
943CommandObjectWatchpointSetVariable::~CommandObjectWatchpointSetVariable ()
944{
945}
946
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000947Options *
Johnny Chen42404d22012-02-08 22:37:48 +0000948CommandObjectWatchpointSetVariable::GetOptions ()
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000949{
950 return &m_option_group;
951}
952
953bool
Johnny Chen42404d22012-02-08 22:37:48 +0000954CommandObjectWatchpointSetVariable::Execute
Johnny Chen55a2d5a2012-01-30 21:46:17 +0000955(
956 Args& command,
957 CommandReturnObject &result
958)
959{
Johnny Chen1e0e73a2012-06-04 20:08:23 +0000960 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Johnny Chen42404d22012-02-08 22:37:48 +0000961 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
962 StackFrame *frame = exe_ctx.GetFramePtr();
963 if (frame == NULL)
964 {
965 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
966 result.SetStatus (eReturnStatusFailed);
967 return false;
968 }
969
970 // If no argument is present, issue an error message. There's no way to set a watchpoint.
971 if (command.GetArgumentCount() <= 0)
972 {
973 result.GetErrorStream().Printf("error: required argument missing; specify your program variable to watch for\n");
974 result.SetStatus(eReturnStatusFailed);
975 return false;
976 }
977
978 // If no '-w' is specified, default to '-w read_write'.
979 if (!m_option_watchpoint.watch_type_specified)
980 {
981 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite;
982 }
983
984 // We passed the sanity check for the command.
985 // Proceed to set the watchpoint now.
986 lldb::addr_t addr = 0;
987 size_t size = 0;
988
989 VariableSP var_sp;
990 ValueObjectSP valobj_sp;
991 Stream &output_stream = result.GetOutputStream();
992
993 // A simple watch variable gesture allows only one argument.
994 if (command.GetArgumentCount() != 1) {
995 result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n");
996 result.SetStatus(eReturnStatusFailed);
997 return false;
998 }
999
1000 // Things have checked out ok...
1001 Error error;
1002 uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
1003 valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0),
1004 eNoDynamicValues,
1005 expr_path_options,
1006 var_sp,
1007 error);
1008 if (valobj_sp) {
1009 AddressType addr_type;
1010 addr = valobj_sp->GetAddressOf(false, &addr_type);
1011 if (addr_type == eAddressTypeLoad) {
1012 // We're in business.
1013 // Find out the size of this variable.
1014 size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize()
1015 : m_option_watchpoint.watch_size;
Johnny Chen1e0e73a2012-06-04 20:08:23 +00001016 if (!m_option_watchpoint.IsWatchSizeSupported(size))
1017 {
1018 result.GetErrorStream().Printf("Watch size of %lu is not supported\n", size);
1019 return false;
1020 }
Johnny Chen42404d22012-02-08 22:37:48 +00001021 }
1022 } else {
1023 const char *error_cstr = error.AsCString(NULL);
1024 if (error_cstr)
1025 result.GetErrorStream().Printf("error: %s\n", error_cstr);
1026 else
1027 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n",
1028 command.GetArgumentAtIndex(0));
1029 return false;
1030 }
1031
1032 // Now it's time to create the watchpoint.
1033 uint32_t watch_type = m_option_watchpoint.watch_type;
Johnny Chen1e0e73a2012-06-04 20:08:23 +00001034 Watchpoint *wp = target->CreateWatchpoint(addr, size, watch_type).get();
Johnny Chen42404d22012-02-08 22:37:48 +00001035 if (wp) {
1036 if (var_sp && var_sp->GetDeclaration().GetFile()) {
1037 StreamString ss;
1038 // True to show fullpath for declaration file.
1039 var_sp->GetDeclaration().DumpStopContext(&ss, true);
1040 wp->SetDeclInfo(ss.GetString());
1041 }
1042 StreamString ss;
1043 output_stream.Printf("Watchpoint created: ");
1044 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1045 output_stream.EOL();
1046 result.SetStatus(eReturnStatusSuccessFinishResult);
1047 } else {
1048 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n",
1049 addr, size);
Johnny Chen1e0e73a2012-06-04 20:08:23 +00001050 CheckIfWatchpointsExhausted(target, result);
Johnny Chen42404d22012-02-08 22:37:48 +00001051 result.SetStatus(eReturnStatusFailed);
1052 }
1053
1054 return result.Succeeded();
1055}
1056
1057//-------------------------------------------------------------------------
1058// CommandObjectWatchpointSetExpression
1059//-------------------------------------------------------------------------
1060#pragma mark Set
1061
1062CommandObjectWatchpointSetExpression::CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) :
1063 CommandObject (interpreter,
1064 "watchpoint set expression",
1065 "Set a watchpoint on an address by supplying an expression. "
1066 "Use the '-w' option to specify the type of watchpoint and "
1067 "the '-x' option to specify the byte size to watch for. "
1068 "If no '-w' option is specified, it defaults to read_write. "
1069 "If no '-x' option is specified, it defaults to the target's "
1070 "pointer byte size. "
Johnny Chen5564b582012-04-27 05:27:07 +00001071 "Note that there are limited hardware resources for watchpoints. "
1072 "If watchpoint setting fails, consider disable/delete existing ones "
1073 "to free up resources.",
Johnny Chen42404d22012-02-08 22:37:48 +00001074 NULL,
1075 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
1076 m_option_group (interpreter),
1077 m_option_watchpoint ()
1078{
1079 SetHelpLong(
1080"Examples: \n\
1081\n\
1082 watchpoint set expression -w write -x 1 -- foo + 32\n\
1083 # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n");
1084
1085 CommandArgumentEntry arg;
1086 CommandArgumentData expression_arg;
1087
1088 // Define the only variant of this arg.
1089 expression_arg.arg_type = eArgTypeExpression;
1090 expression_arg.arg_repetition = eArgRepeatPlain;
1091
1092 // Push the only variant into the argument entry.
1093 arg.push_back (expression_arg);
1094
1095 // Push the data for the only argument into the m_arguments vector.
1096 m_arguments.push_back (arg);
1097
1098 // Absorb the '-w' and '-x' options into our option group.
1099 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
1100 m_option_group.Finalize();
1101}
1102
1103CommandObjectWatchpointSetExpression::~CommandObjectWatchpointSetExpression ()
1104{
1105}
1106
1107Options *
1108CommandObjectWatchpointSetExpression::GetOptions ()
1109{
1110 return &m_option_group;
1111}
1112
1113#include "llvm/ADT/StringRef.h"
1114static inline void StripLeadingSpaces(llvm::StringRef &Str)
1115{
1116 while (!Str.empty() && isspace(Str[0]))
1117 Str = Str.substr(1);
1118}
1119static inline llvm::StringRef StripOptionTerminator(llvm::StringRef &Str, bool with_dash_w, bool with_dash_x)
1120{
1121 llvm::StringRef ExprStr = Str;
1122
1123 // Get rid of the leading spaces first.
1124 StripLeadingSpaces(ExprStr);
1125
1126 // If there's no '-w' and no '-x', we can just return.
1127 if (!with_dash_w && !with_dash_x)
1128 return ExprStr;
1129
1130 // Otherwise, split on the "--" option terminator string, and return the rest of the string.
1131 ExprStr = ExprStr.split("--").second;
1132 StripLeadingSpaces(ExprStr);
1133 return ExprStr;
1134}
1135bool
1136CommandObjectWatchpointSetExpression::ExecuteRawCommandString
1137(
1138 const char *raw_command,
1139 CommandReturnObject &result
1140)
1141{
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001142 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1143 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
1144 StackFrame *frame = exe_ctx.GetFramePtr();
1145 if (frame == NULL)
1146 {
1147 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
1148 result.SetStatus (eReturnStatusFailed);
1149 return false;
1150 }
1151
Johnny Chen42404d22012-02-08 22:37:48 +00001152 Args command(raw_command);
1153
1154 // Process possible options.
1155 if (!ParseOptions (command, result))
1156 return false;
1157
Johnny Chen6183fcc2012-02-08 01:13:31 +00001158 // If no argument is present, issue an error message. There's no way to set a watchpoint.
1159 if (command.GetArgumentCount() <= 0)
1160 {
Johnny Chen42404d22012-02-08 22:37:48 +00001161 result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the addres to watch for\n");
Johnny Chen6183fcc2012-02-08 01:13:31 +00001162 result.SetStatus(eReturnStatusFailed);
1163 return false;
1164 }
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001165
Johnny Chen8c1af792012-02-09 18:44:27 +00001166 bool with_dash_w = m_option_watchpoint.watch_type_specified;
1167 bool with_dash_x = (m_option_watchpoint.watch_size != 0);
Johnny Chen6183fcc2012-02-08 01:13:31 +00001168
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001169 // If no '-w' is specified, default to '-w read_write'.
Johnny Chen8c1af792012-02-09 18:44:27 +00001170 if (!with_dash_w)
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001171 {
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001172 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite;
1173 }
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001174
Johnny Chen6183fcc2012-02-08 01:13:31 +00001175 // We passed the sanity check for the command.
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001176 // Proceed to set the watchpoint now.
1177 lldb::addr_t addr = 0;
1178 size_t size = 0;
1179
1180 VariableSP var_sp;
1181 ValueObjectSP valobj_sp;
1182 Stream &output_stream = result.GetOutputStream();
1183
Johnny Chen42404d22012-02-08 22:37:48 +00001184 // We will process the raw command string to rid of the '-w', '-x', or '--'
1185 llvm::StringRef raw_expr_str(raw_command);
Johnny Chen8c1af792012-02-09 18:44:27 +00001186 std::string expr_str = StripOptionTerminator(raw_expr_str, with_dash_w, with_dash_x).str();
1187
1188 // Sanity check for when the user forgets to terminate the option strings with a '--'.
1189 if ((with_dash_w || with_dash_w) && expr_str.empty())
1190 {
1191 result.GetErrorStream().Printf("error: did you forget to enter the option terminator string \"--\"?\n");
1192 result.SetStatus(eReturnStatusFailed);
1193 return false;
1194 }
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001195
Johnny Chen42404d22012-02-08 22:37:48 +00001196 // Use expression evaluation to arrive at the address to watch.
1197 const bool coerce_to_id = true;
1198 const bool unwind_on_error = true;
1199 const bool keep_in_memory = false;
1200 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(),
1201 frame,
1202 eExecutionPolicyOnlyWhenNeeded,
1203 coerce_to_id,
1204 unwind_on_error,
1205 keep_in_memory,
1206 eNoDynamicValues,
1207 valobj_sp);
1208 if (expr_result != eExecutionCompleted) {
1209 result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n");
1210 result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str());
1211 result.SetStatus(eReturnStatusFailed);
Johnny Chen8c1af792012-02-09 18:44:27 +00001212 return false;
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001213 }
1214
Johnny Chen42404d22012-02-08 22:37:48 +00001215 // Get the address to watch.
1216 addr = valobj_sp->GetValueAsUnsigned(0);
1217 if (!addr) {
1218 result.GetErrorStream().Printf("error: expression did not evaluate to an address\n");
1219 result.SetStatus(eReturnStatusFailed);
1220 return false;
1221 }
Johnny Chen8c1af792012-02-09 18:44:27 +00001222 size = with_dash_x ? m_option_watchpoint.watch_size
1223 : target->GetArchitecture().GetAddressByteSize();
Johnny Chen1e0e73a2012-06-04 20:08:23 +00001224 if (!m_option_watchpoint.IsWatchSizeSupported(size))
1225 {
1226 result.GetErrorStream().Printf("Watch size of %lu is not supported\n", size);
1227 return false;
1228 }
Johnny Chen42404d22012-02-08 22:37:48 +00001229
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001230 // Now it's time to create the watchpoint.
1231 uint32_t watch_type = m_option_watchpoint.watch_type;
Johnny Chen1e0e73a2012-06-04 20:08:23 +00001232 Watchpoint *wp = target->CreateWatchpoint(addr, size, watch_type).get();
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001233 if (wp) {
1234 if (var_sp && var_sp->GetDeclaration().GetFile()) {
1235 StreamString ss;
1236 // True to show fullpath for declaration file.
1237 var_sp->GetDeclaration().DumpStopContext(&ss, true);
1238 wp->SetDeclInfo(ss.GetString());
1239 }
1240 StreamString ss;
1241 output_stream.Printf("Watchpoint created: ");
1242 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
1243 output_stream.EOL();
1244 result.SetStatus(eReturnStatusSuccessFinishResult);
1245 } else {
Johnny Chen6183fcc2012-02-08 01:13:31 +00001246 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n",
1247 addr, size);
Johnny Chen1e0e73a2012-06-04 20:08:23 +00001248 CheckIfWatchpointsExhausted(target, result);
Johnny Chen55a2d5a2012-01-30 21:46:17 +00001249 result.SetStatus(eReturnStatusFailed);
1250 }
1251
1252 return result.Succeeded();
1253}