blob: 45291a54bdb9b1ae5be9947d6e09dfb2f9e13e86 [file] [log] [blame]
Johnny Chene9a56272012-08-09 23:09:42 +00001//===-- CommandObjectWatchpointCommand.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 Chene9a56272012-08-09 23:09:42 +000012// C Includes
13// C++ Includes
14
15
16#include "CommandObjectWatchpointCommand.h"
17#include "CommandObjectWatchpoint.h"
18
Greg Clayton44d93782014-01-27 23:43:24 +000019#include "lldb/Core/IOHandler.h"
Johnny Chene9a56272012-08-09 23:09:42 +000020#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
22#include "lldb/Target/Target.h"
23#include "lldb/Target/Thread.h"
24#include "lldb/Breakpoint/Watchpoint.h"
25#include "lldb/Breakpoint/StoppointCallbackContext.h"
26#include "lldb/Core/State.h"
27
28#include <vector>
29
30using namespace lldb;
31using namespace lldb_private;
32
33//-------------------------------------------------------------------------
34// CommandObjectWatchpointCommandAdd
35//-------------------------------------------------------------------------
36
37
Greg Clayton44d93782014-01-27 23:43:24 +000038class CommandObjectWatchpointCommandAdd :
39 public CommandObjectParsed,
40 public IOHandlerDelegateMultiline
Johnny Chene9a56272012-08-09 23:09:42 +000041{
42public:
43
44 CommandObjectWatchpointCommandAdd (CommandInterpreter &interpreter) :
45 CommandObjectParsed (interpreter,
46 "add",
47 "Add a set of commands to a watchpoint, to be executed whenever the watchpoint is hit.",
48 NULL),
Greg Claytonf29bf9a2014-05-02 01:03:07 +000049 IOHandlerDelegateMultiline("DONE", true, IOHandlerDelegate::Completion::LLDBCommand),
Johnny Chene9a56272012-08-09 23:09:42 +000050 m_options (interpreter)
51 {
52 SetHelpLong (
53"\nGeneral information about entering watchpoint commands \n\
54------------------------------------------------------ \n\
55 \n\
56This command will cause you to be prompted to enter the command or set \n\
57of commands you wish to be executed when the specified watchpoint is \n\
58hit. You will be told to enter your command(s), and will see a '> ' \n\
59prompt. Because you can enter one or many commands to be executed when \n\
60a watchpoint is hit, you will continue to be prompted after each \n\
61new-line that you enter, until you enter the word 'DONE', which will \n\
62cause the commands you have entered to be stored with the watchpoint \n\
63and executed when the watchpoint is hit. \n\
64 \n\
65Syntax checking is not necessarily done when watchpoint commands are \n\
66entered. An improperly written watchpoint command will attempt to get \n\
67executed when the watchpoint gets hit, and usually silently fail. If \n\
68your watchpoint command does not appear to be getting executed, go \n\
69back and check your syntax. \n\
70 \n\
71 \n\
72Special information about PYTHON watchpoint commands \n\
73---------------------------------------------------- \n\
74 \n\
75You may enter either one line of Python or multiple lines of Python \n\
76(including defining whole functions, if desired). If you enter a \n\
77single line of Python, that will be passed to the Python interpreter \n\
78'as is' when the watchpoint gets hit. If you enter function \n\
79definitions, they will be passed to the Python interpreter as soon as \n\
80you finish entering the watchpoint command, and they can be called \n\
81later (don't forget to add calls to them, if you want them called when \n\
82the watchpoint is hit). If you enter multiple lines of Python that \n\
83are not function definitions, they will be collected into a new, \n\
84automatically generated Python function, and a call to the newly \n\
85generated function will be attached to the watchpoint. \n\
86 \n\
87This auto-generated function is passed in two arguments: \n\
88 \n\
89 frame: an SBFrame object representing the frame which hit the watchpoint. \n\
90 From the frame you can get back to the thread and process. \n\
91 wp: the watchpoint that was hit. \n\
92 \n\
93Important Note: Because loose Python code gets collected into functions, \n\
94if you want to access global variables in the 'loose' code, you need to \n\
95specify that they are global, using the 'global' keyword. Be sure to \n\
96use correct Python syntax, including indentation, when entering Python \n\
97watchpoint commands. \n\
98 \n\
99As a third option, you can pass the name of an already existing Python function \n\
100and that function will be attached to the watchpoint. It will get passed the \n\
101frame and wp_loc arguments mentioned above. \n\
102 \n\
103Example Python one-line watchpoint command: \n\
104 \n\
105(lldb) watchpoint command add -s python 1 \n\
106Enter your Python command(s). Type 'DONE' to end. \n\
107> print \"Hit this watchpoint!\" \n\
108> DONE \n\
109 \n\
110As a convenience, this also works for a short Python one-liner: \n\
111(lldb) watchpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
112(lldb) run \n\
113Launching '.../a.out' (x86_64) \n\
114(lldb) Fri Sep 10 12:17:45 2010 \n\
115Process 21778 Stopped \n\
116* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = watchpoint 1.1, queue = com.apple.main-thread \n\
117 36 \n\
118 37 int c(int val)\n\
119 38 {\n\
120 39 -> return val + 3;\n\
121 40 }\n\
122 41 \n\
123 42 int main (int argc, char const *argv[])\n\
124(lldb) \n\
125 \n\
126Example multiple line Python watchpoint command, using function definition: \n\
127 \n\
128(lldb) watchpoint command add -s python 1 \n\
129Enter your Python command(s). Type 'DONE' to end. \n\
130> def watchpoint_output (wp_no): \n\
131> out_string = \"Hit watchpoint number \" + repr (wp_no) \n\
132> print out_string \n\
133> return True \n\
134> watchpoint_output (1) \n\
135> DONE \n\
136 \n\
137 \n\
138Example multiple line Python watchpoint command, using 'loose' Python: \n\
139 \n\
140(lldb) watchpoint command add -s p 1 \n\
141Enter your Python command(s). Type 'DONE' to end. \n\
142> global wp_count \n\
143> wp_count = wp_count + 1 \n\
144> print \"Hit this watchpoint \" + repr(wp_count) + \" times!\" \n\
145> DONE \n\
146 \n\
147In this case, since there is a reference to a global variable, \n\
148'wp_count', you will also need to make sure 'wp_count' exists and is \n\
149initialized: \n\
150 \n\
151(lldb) script \n\
152>>> wp_count = 0 \n\
153>>> quit() \n\
154 \n\
155(lldb) \n\
156 \n\
157 \n\
158Final Note: If you get a warning that no watchpoint command was generated, \n\
159but you did not get any syntax errors, you probably forgot to add a call \n\
160to your functions. \n\
161 \n\
162Special information about debugger command watchpoint commands \n\
163-------------------------------------------------------------- \n\
164 \n\
165You may enter any debugger command, exactly as you would at the \n\
166debugger prompt. You may enter as many debugger commands as you like, \n\
167but do NOT enter more than one command per line. \n" );
168
169 CommandArgumentEntry arg;
170 CommandArgumentData wp_id_arg;
171
172 // Define the first (and only) variant of this arg.
173 wp_id_arg.arg_type = eArgTypeWatchpointID;
174 wp_id_arg.arg_repetition = eArgRepeatPlain;
175
176 // There is only one variant this argument could be; put it into the argument entry.
177 arg.push_back (wp_id_arg);
178
179 // Push the data for the first argument into the m_arguments vector.
180 m_arguments.push_back (arg);
181 }
182
183 virtual
184 ~CommandObjectWatchpointCommandAdd () {}
185
186 virtual Options *
187 GetOptions ()
188 {
189 return &m_options;
190 }
191
Greg Clayton44d93782014-01-27 23:43:24 +0000192 virtual void
193 IOHandlerActivated (IOHandler &io_handler)
194 {
195 StreamFileSP output_sp(io_handler.GetOutputStreamFile());
196 if (output_sp)
197 {
198 output_sp->PutCString("Enter your debugger command(s). Type 'DONE' to end.\n");
199 output_sp->Flush();
200 }
201 }
202
203
204 virtual void
205 IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
206 {
207 io_handler.SetIsDone(true);
208
209 // The WatchpointOptions object is owned by the watchpoint or watchpoint location
210 WatchpointOptions *wp_options = (WatchpointOptions *) io_handler.GetUserData();
211 if (wp_options)
212 {
213 std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
214 if (data_ap.get())
215 {
216 data_ap->user_source.SplitIntoLines(line);
217 BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
218 wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
219 }
220 }
221 }
222
Johnny Chene9a56272012-08-09 23:09:42 +0000223 void
224 CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
225 CommandReturnObject &result)
226 {
Greg Clayton44d93782014-01-27 23:43:24 +0000227 m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt
228 *this, // IOHandlerDelegate
229 true, // Run IOHandler in async mode
230 wp_options); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
Johnny Chene9a56272012-08-09 23:09:42 +0000231 }
232
233 /// Set a one-liner as the callback for the watchpoint.
234 void
235 SetWatchpointCommandCallback (WatchpointOptions *wp_options,
236 const char *oneliner)
237 {
Greg Clayton7b0992d2013-04-18 22:45:39 +0000238 std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
Johnny Chene9a56272012-08-09 23:09:42 +0000239
240 // It's necessary to set both user_source and script_source to the oneliner.
241 // The former is used to generate callback description (as in watchpoint command list)
242 // while the latter is used for Python to interpret during the actual callback.
243 data_ap->user_source.AppendString (oneliner);
244 data_ap->script_source.assign (oneliner);
245 data_ap->stop_on_error = m_options.m_stop_on_error;
246
247 BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
248 wp_options->SetCallback (WatchpointOptionsCallbackFunction, baton_sp);
249
250 return;
251 }
Johnny Chene9a56272012-08-09 23:09:42 +0000252
253 static bool
254 WatchpointOptionsCallbackFunction (void *baton,
255 StoppointCallbackContext *context,
256 lldb::user_id_t watch_id)
257 {
258 bool ret_value = true;
259 if (baton == NULL)
260 return true;
261
262
263 WatchpointOptions::CommandData *data = (WatchpointOptions::CommandData *) baton;
264 StringList &commands = data->user_source;
265
266 if (commands.GetSize() > 0)
267 {
268 ExecutionContext exe_ctx (context->exe_ctx_ref);
269 Target *target = exe_ctx.GetTargetPtr();
270 if (target)
271 {
272 CommandReturnObject result;
273 Debugger &debugger = target->GetDebugger();
274 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
275 // if the debugger is set up that way.
276
277 StreamSP output_stream (debugger.GetAsyncOutputStream());
278 StreamSP error_stream (debugger.GetAsyncErrorStream());
279 result.SetImmediateOutputStream (output_stream);
280 result.SetImmediateErrorStream (error_stream);
281
282 bool stop_on_continue = true;
283 bool echo_commands = false;
284 bool print_results = true;
285
286 debugger.GetCommandInterpreter().HandleCommands (commands,
287 &exe_ctx,
288 stop_on_continue,
289 data->stop_on_error,
290 echo_commands,
291 print_results,
292 eLazyBoolNo,
293 result);
294 result.GetImmediateOutputStream()->Flush();
295 result.GetImmediateErrorStream()->Flush();
296 }
297 }
298 return ret_value;
299 }
300
301 class CommandOptions : public Options
302 {
303 public:
304
305 CommandOptions (CommandInterpreter &interpreter) :
306 Options (interpreter),
307 m_use_commands (false),
308 m_use_script_language (false),
309 m_script_language (eScriptLanguageNone),
310 m_use_one_liner (false),
311 m_one_liner(),
312 m_function_name()
313 {
314 }
315
316 virtual
317 ~CommandOptions () {}
318
319 virtual Error
320 SetOptionValue (uint32_t option_idx, const char *option_arg)
321 {
322 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000323 const int short_option = m_getopt_table[option_idx].val;
Johnny Chene9a56272012-08-09 23:09:42 +0000324
325 switch (short_option)
326 {
327 case 'o':
328 m_use_one_liner = true;
329 m_one_liner = option_arg;
330 break;
331
332 case 's':
333 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
334 g_option_table[option_idx].enum_values,
335 eScriptLanguageNone,
336 error);
337
338 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
339 {
340 m_use_script_language = true;
341 }
342 else
343 {
344 m_use_script_language = false;
345 }
346 break;
347
348 case 'e':
349 {
350 bool success = false;
351 m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
352 if (!success)
353 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
354 }
355 break;
356
357 case 'F':
358 {
359 m_use_one_liner = false;
360 m_use_script_language = true;
361 m_function_name.assign(option_arg);
362 }
363 break;
364
365 default:
366 break;
367 }
368 return error;
369 }
370 void
371 OptionParsingStarting ()
372 {
373 m_use_commands = true;
374 m_use_script_language = false;
375 m_script_language = eScriptLanguageNone;
376
377 m_use_one_liner = false;
378 m_stop_on_error = true;
379 m_one_liner.clear();
380 m_function_name.clear();
381 }
382
383 const OptionDefinition*
384 GetDefinitions ()
385 {
386 return g_option_table;
387 }
388
389 // Options table: Required for subclasses of Options.
390
391 static OptionDefinition g_option_table[];
392
393 // Instance variables to hold the values for command options.
394
395 bool m_use_commands;
396 bool m_use_script_language;
397 lldb::ScriptLanguage m_script_language;
398
399 // Instance variables to hold the values for one_liner options.
400 bool m_use_one_liner;
401 std::string m_one_liner;
402 bool m_stop_on_error;
403 std::string m_function_name;
404 };
405
406protected:
407 virtual bool
408 DoExecute (Args& command, CommandReturnObject &result)
409 {
410 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
411
412 if (target == NULL)
413 {
414 result.AppendError ("There is not a current executable; there are no watchpoints to which to add commands");
415 result.SetStatus (eReturnStatusFailed);
416 return false;
417 }
418
419 const WatchpointList &watchpoints = target->GetWatchpointList();
420 size_t num_watchpoints = watchpoints.GetSize();
421
422 if (num_watchpoints == 0)
423 {
424 result.AppendError ("No watchpoints exist to have commands added");
425 result.SetStatus (eReturnStatusFailed);
426 return false;
427 }
428
429 if (m_options.m_use_script_language == false && m_options.m_function_name.size())
430 {
431 result.AppendError ("need to enable scripting to have a function run as a watchpoint command");
432 result.SetStatus (eReturnStatusFailed);
433 return false;
434 }
435
436 std::vector<uint32_t> valid_wp_ids;
Jim Inghamb0b45132013-07-02 02:09:46 +0000437 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
Johnny Chene9a56272012-08-09 23:09:42 +0000438 {
439 result.AppendError("Invalid watchpoints specification.");
440 result.SetStatus(eReturnStatusFailed);
441 return false;
442 }
443
444 result.SetStatus(eReturnStatusSuccessFinishNoResult);
445 const size_t count = valid_wp_ids.size();
446 for (size_t i = 0; i < count; ++i)
447 {
448 uint32_t cur_wp_id = valid_wp_ids.at (i);
449 if (cur_wp_id != LLDB_INVALID_WATCH_ID)
450 {
451 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
452 // Sanity check wp first.
453 if (wp == NULL) continue;
454
455 WatchpointOptions *wp_options = wp->GetOptions();
456 // Skip this watchpoint if wp_options is not good.
457 if (wp_options == NULL) continue;
458
459 // If we are using script language, get the script interpreter
460 // in order to set or collect command callback. Otherwise, call
461 // the methods associated with this object.
462 if (m_options.m_use_script_language)
463 {
464 // Special handling for one-liner specified inline.
465 if (m_options.m_use_one_liner)
466 {
467 m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options,
468 m_options.m_one_liner.c_str());
469 }
470 // Special handling for using a Python function by name
471 // instead of extending the watchpoint callback data structures, we just automatize
472 // what the user would do manually: make their watchpoint command be a function call
473 else if (m_options.m_function_name.size())
474 {
475 std::string oneliner(m_options.m_function_name);
476 oneliner += "(frame, wp, internal_dict)";
477 m_interpreter.GetScriptInterpreter()->SetWatchpointCommandCallback (wp_options,
478 oneliner.c_str());
479 }
480 else
481 {
482 m_interpreter.GetScriptInterpreter()->CollectDataForWatchpointCommandCallback (wp_options,
483 result);
484 }
485 }
486 else
487 {
488 // Special handling for one-liner specified inline.
489 if (m_options.m_use_one_liner)
490 SetWatchpointCommandCallback (wp_options,
491 m_options.m_one_liner.c_str());
492 else
493 CollectDataForWatchpointCommandCallback (wp_options,
494 result);
495 }
496 }
497 }
498
499 return result.Succeeded();
500 }
501
502private:
503 CommandOptions m_options;
Johnny Chene9a56272012-08-09 23:09:42 +0000504};
505
Johnny Chene9a56272012-08-09 23:09:42 +0000506
507// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
508// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
509
510static OptionEnumValueElement
511g_script_option_enumeration[4] =
512{
513 { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
514 { eScriptLanguagePython, "python", "Commands are in the Python language."},
515 { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
516 { 0, NULL, NULL }
517};
518
519OptionDefinition
520CommandObjectWatchpointCommandAdd::CommandOptions::g_option_table[] =
521{
Virgile Belloe2607b52013-09-05 16:42:23 +0000522 { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOneLiner,
Johnny Chene9a56272012-08-09 23:09:42 +0000523 "Specify a one-line watchpoint command inline. Be sure to surround it with quotes." },
524
Virgile Belloe2607b52013-09-05 16:42:23 +0000525 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean,
Johnny Chene9a56272012-08-09 23:09:42 +0000526 "Specify whether watchpoint command execution should terminate on error." },
527
Virgile Belloe2607b52013-09-05 16:42:23 +0000528 { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, g_script_option_enumeration, 0, eArgTypeNone,
Johnny Chene9a56272012-08-09 23:09:42 +0000529 "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
530
Virgile Belloe2607b52013-09-05 16:42:23 +0000531 { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, 0, eArgTypePythonFunction,
Johnny Chene9a56272012-08-09 23:09:42 +0000532 "Give the name of a Python function to run as command for this watchpoint. Be sure to give a module name if appropriate."},
533
534 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
535};
536
537//-------------------------------------------------------------------------
538// CommandObjectWatchpointCommandDelete
539//-------------------------------------------------------------------------
540
541class CommandObjectWatchpointCommandDelete : public CommandObjectParsed
542{
543public:
544 CommandObjectWatchpointCommandDelete (CommandInterpreter &interpreter) :
545 CommandObjectParsed (interpreter,
546 "delete",
547 "Delete the set of commands from a watchpoint.",
548 NULL)
549 {
550 CommandArgumentEntry arg;
551 CommandArgumentData wp_id_arg;
552
553 // Define the first (and only) variant of this arg.
554 wp_id_arg.arg_type = eArgTypeWatchpointID;
555 wp_id_arg.arg_repetition = eArgRepeatPlain;
556
557 // There is only one variant this argument could be; put it into the argument entry.
558 arg.push_back (wp_id_arg);
559
560 // Push the data for the first argument into the m_arguments vector.
561 m_arguments.push_back (arg);
562 }
563
564
565 virtual
566 ~CommandObjectWatchpointCommandDelete () {}
567
568protected:
569 virtual bool
570 DoExecute (Args& command, CommandReturnObject &result)
571 {
572 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
573
574 if (target == NULL)
575 {
576 result.AppendError ("There is not a current executable; there are no watchpoints from which to delete commands");
577 result.SetStatus (eReturnStatusFailed);
578 return false;
579 }
580
581 const WatchpointList &watchpoints = target->GetWatchpointList();
582 size_t num_watchpoints = watchpoints.GetSize();
583
584 if (num_watchpoints == 0)
585 {
586 result.AppendError ("No watchpoints exist to have commands deleted");
587 result.SetStatus (eReturnStatusFailed);
588 return false;
589 }
590
591 if (command.GetArgumentCount() == 0)
592 {
593 result.AppendError ("No watchpoint specified from which to delete the commands");
594 result.SetStatus (eReturnStatusFailed);
595 return false;
596 }
597
598 std::vector<uint32_t> valid_wp_ids;
Jim Inghamb0b45132013-07-02 02:09:46 +0000599 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
Johnny Chene9a56272012-08-09 23:09:42 +0000600 {
601 result.AppendError("Invalid watchpoints specification.");
602 result.SetStatus(eReturnStatusFailed);
603 return false;
604 }
605
606 result.SetStatus(eReturnStatusSuccessFinishNoResult);
607 const size_t count = valid_wp_ids.size();
608 for (size_t i = 0; i < count; ++i)
609 {
610 uint32_t cur_wp_id = valid_wp_ids.at (i);
611 if (cur_wp_id != LLDB_INVALID_WATCH_ID)
612 {
613 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
614 if (wp)
615 wp->ClearCallback();
616 }
617 else
618 {
619 result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n",
620 cur_wp_id);
621 result.SetStatus (eReturnStatusFailed);
622 return false;
623 }
624 }
625 return result.Succeeded();
626 }
627};
628
629//-------------------------------------------------------------------------
630// CommandObjectWatchpointCommandList
631//-------------------------------------------------------------------------
632
633class CommandObjectWatchpointCommandList : public CommandObjectParsed
634{
635public:
636 CommandObjectWatchpointCommandList (CommandInterpreter &interpreter) :
637 CommandObjectParsed (interpreter,
638 "list",
639 "List the script or set of commands to be executed when the watchpoint is hit.",
640 NULL)
641 {
642 CommandArgumentEntry arg;
643 CommandArgumentData wp_id_arg;
644
645 // Define the first (and only) variant of this arg.
646 wp_id_arg.arg_type = eArgTypeWatchpointID;
647 wp_id_arg.arg_repetition = eArgRepeatPlain;
648
649 // There is only one variant this argument could be; put it into the argument entry.
650 arg.push_back (wp_id_arg);
651
652 // Push the data for the first argument into the m_arguments vector.
653 m_arguments.push_back (arg);
654 }
655
656 virtual
657 ~CommandObjectWatchpointCommandList () {}
658
659protected:
660 virtual bool
661 DoExecute (Args& command,
662 CommandReturnObject &result)
663 {
664 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
665
666 if (target == NULL)
667 {
668 result.AppendError ("There is not a current executable; there are no watchpoints for which to list commands");
669 result.SetStatus (eReturnStatusFailed);
670 return false;
671 }
672
673 const WatchpointList &watchpoints = target->GetWatchpointList();
674 size_t num_watchpoints = watchpoints.GetSize();
675
676 if (num_watchpoints == 0)
677 {
678 result.AppendError ("No watchpoints exist for which to list commands");
679 result.SetStatus (eReturnStatusFailed);
680 return false;
681 }
682
683 if (command.GetArgumentCount() == 0)
684 {
685 result.AppendError ("No watchpoint specified for which to list the commands");
686 result.SetStatus (eReturnStatusFailed);
687 return false;
688 }
689
690 std::vector<uint32_t> valid_wp_ids;
Jim Inghamb0b45132013-07-02 02:09:46 +0000691 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, valid_wp_ids))
Johnny Chene9a56272012-08-09 23:09:42 +0000692 {
693 result.AppendError("Invalid watchpoints specification.");
694 result.SetStatus(eReturnStatusFailed);
695 return false;
696 }
697
698 result.SetStatus(eReturnStatusSuccessFinishNoResult);
699 const size_t count = valid_wp_ids.size();
700 for (size_t i = 0; i < count; ++i)
701 {
702 uint32_t cur_wp_id = valid_wp_ids.at (i);
703 if (cur_wp_id != LLDB_INVALID_WATCH_ID)
704 {
705 Watchpoint *wp = target->GetWatchpointList().FindByID (cur_wp_id).get();
706
707 if (wp)
708 {
709 const WatchpointOptions *wp_options = wp->GetOptions();
710 if (wp_options)
711 {
712 // Get the callback baton associated with the current watchpoint.
713 const Baton *baton = wp_options->GetBaton();
714 if (baton)
715 {
716 result.GetOutputStream().Printf ("Watchpoint %u:\n", cur_wp_id);
717 result.GetOutputStream().IndentMore ();
718 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
719 result.GetOutputStream().IndentLess ();
720 }
721 else
722 {
723 result.AppendMessageWithFormat ("Watchpoint %u does not have an associated command.\n",
724 cur_wp_id);
725 }
726 }
727 result.SetStatus (eReturnStatusSuccessFinishResult);
728 }
729 else
730 {
731 result.AppendErrorWithFormat("Invalid watchpoint ID: %u.\n", cur_wp_id);
732 result.SetStatus (eReturnStatusFailed);
733 }
734 }
735 }
736
737 return result.Succeeded();
738 }
739};
740
741//-------------------------------------------------------------------------
742// CommandObjectWatchpointCommand
743//-------------------------------------------------------------------------
744
745CommandObjectWatchpointCommand::CommandObjectWatchpointCommand (CommandInterpreter &interpreter) :
746 CommandObjectMultiword (interpreter,
747 "command",
748 "A set of commands for adding, removing and examining bits of code to be executed when the watchpoint is hit (watchpoint 'commmands').",
749 "command <sub-command> [<sub-command-options>] <watchpoint-id>")
750{
Johnny Chene9a56272012-08-09 23:09:42 +0000751 CommandObjectSP add_command_object (new CommandObjectWatchpointCommandAdd (interpreter));
752 CommandObjectSP delete_command_object (new CommandObjectWatchpointCommandDelete (interpreter));
753 CommandObjectSP list_command_object (new CommandObjectWatchpointCommandList (interpreter));
754
755 add_command_object->SetCommandName ("watchpoint command add");
756 delete_command_object->SetCommandName ("watchpoint command delete");
757 list_command_object->SetCommandName ("watchpoint command list");
758
Greg Clayton03da4cc2013-04-19 21:31:16 +0000759 LoadSubCommand ("add", add_command_object);
760 LoadSubCommand ("delete", delete_command_object);
761 LoadSubCommand ("list", list_command_object);
Johnny Chene9a56272012-08-09 23:09:42 +0000762}
763
764CommandObjectWatchpointCommand::~CommandObjectWatchpointCommand ()
765{
766}
767
768