1 //===-- CommandObjectBreakpointCommand.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 // C Includes
11 // C++ Includes
12 
13 
14 #include "CommandObjectBreakpointCommand.h"
15 #include "CommandObjectBreakpoint.h"
16 
17 #include "lldb/Interpreter/CommandInterpreter.h"
18 #include "lldb/Interpreter/CommandReturnObject.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Target/Thread.h"
21 #include "lldb/Breakpoint/BreakpointIDList.h"
22 #include "lldb/Breakpoint/Breakpoint.h"
23 #include "lldb/Breakpoint/BreakpointLocation.h"
24 #include "lldb/Breakpoint/StoppointCallbackContext.h"
25 #include "lldb/Core/State.h"
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 
30 //-------------------------------------------------------------------------
31 // CommandObjectBreakpointCommandAdd::CommandOptions
32 //-------------------------------------------------------------------------
33 
34 CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions (CommandInterpreter &interpreter) :
35     Options (interpreter),
36     m_use_commands (false),
37     m_use_script_language (false),
38     m_script_language (eScriptLanguageNone),
39     m_use_one_liner (false),
40     m_one_liner(),
41     m_function_name()
42 {
43 }
44 
45 CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions ()
46 {
47 }
48 
49 // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
50 // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
51 
52 static OptionEnumValueElement
53 g_script_option_enumeration[4] =
54 {
55     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
56     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
57     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
58     { 0,                      NULL,              NULL }
59 };
60 
61 OptionDefinition
62 CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
63 {
64     { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner,
65         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
66 
67     { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, NULL, eArgTypeBoolean,
68         "Specify whether breakpoint command execution should terminate on error." },
69 
70     { LLDB_OPT_SET_ALL,   false, "script-type",     's', required_argument, g_script_option_enumeration, NULL, eArgTypeNone,
71         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
72 
73     { LLDB_OPT_SET_2,   false, "python-function",     'F', required_argument, NULL, NULL, eArgTypePythonFunction,
74         "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
75 
76     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
77 };
78 
79 const OptionDefinition*
80 CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
81 {
82     return g_option_table;
83 }
84 
85 
86 Error
87 CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
88 (
89     uint32_t option_idx,
90     const char *option_arg
91 )
92 {
93     Error error;
94     char short_option = (char) m_getopt_table[option_idx].val;
95 
96     switch (short_option)
97     {
98     case 'o':
99         m_use_one_liner = true;
100         m_one_liner = option_arg;
101         break;
102 
103     case 's':
104         m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
105                                                                              g_option_table[option_idx].enum_values,
106                                                                              eScriptLanguageNone,
107                                                                              error);
108 
109         if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
110         {
111             m_use_script_language = true;
112         }
113         else
114         {
115             m_use_script_language = false;
116         }
117         break;
118 
119     case 'e':
120         {
121             bool success = false;
122             m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
123             if (!success)
124                 error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
125         }
126         break;
127 
128     case 'F':
129         {
130             m_use_one_liner = false;
131             m_use_script_language = true;
132             m_function_name.assign(option_arg);
133         }
134         break;
135 
136     default:
137         break;
138     }
139     return error;
140 }
141 
142 void
143 CommandObjectBreakpointCommandAdd::CommandOptions::OptionParsingStarting ()
144 {
145     m_use_commands = true;
146     m_use_script_language = false;
147     m_script_language = eScriptLanguageNone;
148 
149     m_use_one_liner = false;
150     m_stop_on_error = true;
151     m_one_liner.clear();
152     m_function_name.clear();
153 }
154 
155 //-------------------------------------------------------------------------
156 // CommandObjectBreakpointCommandAdd
157 //-------------------------------------------------------------------------
158 
159 
160 CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
161     CommandObject (interpreter,
162                    "add",
163                    "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.",
164                    NULL),
165     m_options (interpreter)
166 {
167     SetHelpLong (
168 "\nGeneral information about entering breakpoint commands \n\
169 ------------------------------------------------------ \n\
170  \n\
171 This command will cause you to be prompted to enter the command or set \n\
172 of commands you wish to be executed when the specified breakpoint is \n\
173 hit.  You will be told to enter your command(s), and will see a '> ' \n\
174 prompt. Because you can enter one or many commands to be executed when \n\
175 a breakpoint is hit, you will continue to be prompted after each \n\
176 new-line that you enter, until you enter the word 'DONE', which will \n\
177 cause the commands you have entered to be stored with the breakpoint \n\
178 and executed when the breakpoint is hit. \n\
179  \n\
180 Syntax checking is not necessarily done when breakpoint commands are \n\
181 entered.  An improperly written breakpoint command will attempt to get \n\
182 executed when the breakpoint gets hit, and usually silently fail.  If \n\
183 your breakpoint command does not appear to be getting executed, go \n\
184 back and check your syntax. \n\
185  \n\
186  \n\
187 Special information about PYTHON breakpoint commands \n\
188 ---------------------------------------------------- \n\
189  \n\
190 You may enter either one line of Python or multiple lines of Python \n\
191 (including defining whole functions, if desired).  If you enter a \n\
192 single line of Python, that will be passed to the Python interpreter \n\
193 'as is' when the breakpoint gets hit.  If you enter function \n\
194 definitions, they will be passed to the Python interpreter as soon as \n\
195 you finish entering the breakpoint command, and they can be called \n\
196 later (don't forget to add calls to them, if you want them called when \n\
197 the breakpoint is hit).  If you enter multiple lines of Python that \n\
198 are not function definitions, they will be collected into a new, \n\
199 automatically generated Python function, and a call to the newly \n\
200 generated function will be attached to the breakpoint.  Important \n\
201 Note: Because loose Python code gets collected into functions, if you \n\
202 want to access global variables in the 'loose' code, you need to \n\
203 specify that they are global, using the 'global' keyword.  Be sure to \n\
204 use correct Python syntax, including indentation, when entering Python \n\
205 breakpoint commands. \nAs a third option, you can pass the name of an already \
206 existing Python function and that function will be attached to the breakpoint. \n\
207  \n\
208 Example Python one-line breakpoint command: \n\
209  \n\
210 (lldb) breakpoint command add -s python 1 \n\
211 Enter your Python command(s). Type 'DONE' to end. \n\
212 > print \"Hit this breakpoint!\" \n\
213 > DONE \n\
214  \n\
215 As a convenience, this also works for a short Python one-liner: \n\
216 (lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\" \n\
217 (lldb) run \n\
218 Launching '.../a.out'  (x86_64) \n\
219 (lldb) Fri Sep 10 12:17:45 2010 \n\
220 Process 21778 Stopped \n\
221 * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread \n\
222   36   	\n\
223   37   	int c(int val)\n\
224   38   	{\n\
225   39 ->	    return val + 3;\n\
226   40   	}\n\
227   41   	\n\
228   42   	int main (int argc, char const *argv[])\n\
229 (lldb) \n\
230  \n\
231 Example multiple line Python breakpoint command, using function definition: \n\
232  \n\
233 (lldb) breakpoint command add -s python 1 \n\
234 Enter your Python command(s). Type 'DONE' to end. \n\
235 > def breakpoint_output (bp_no): \n\
236 >     out_string = \"Hit breakpoint number \" + repr (bp_no) \n\
237 >     print out_string \n\
238 >     return True \n\
239 > breakpoint_output (1) \n\
240 > DONE \n\
241  \n\
242  \n\
243 Example multiple line Python breakpoint command, using 'loose' Python: \n\
244  \n\
245 (lldb) breakpoint command add -s p 1 \n\
246 Enter your Python command(s). Type 'DONE' to end. \n\
247 > global bp_count \n\
248 > bp_count = bp_count + 1 \n\
249 > print \"Hit this breakpoint \" + repr(bp_count) + \" times!\" \n\
250 > DONE \n\
251  \n\
252 In this case, since there is a reference to a global variable, \n\
253 'bp_count', you will also need to make sure 'bp_count' exists and is \n\
254 initialized: \n\
255  \n\
256 (lldb) script \n\
257 >>> bp_count = 0 \n\
258 >>> quit() \n\
259  \n\
260 (lldb)  \n\
261  \n\
262  \n\
263 Final Note:  If you get a warning that no breakpoint command was generated, \n\
264 but you did not get any syntax errors, you probably forgot to add a call \n\
265 to your functions. \n\
266  \n\
267 Special information about debugger command breakpoint commands \n\
268 -------------------------------------------------------------- \n\
269  \n\
270 You may enter any debugger command, exactly as you would at the \n\
271 debugger prompt.  You may enter as many debugger commands as you like, \n\
272 but do NOT enter more than one command per line. \n" );
273 
274 
275     CommandArgumentEntry arg;
276     CommandArgumentData bp_id_arg;
277 
278     // Define the first (and only) variant of this arg.
279     bp_id_arg.arg_type = eArgTypeBreakpointID;
280     bp_id_arg.arg_repetition = eArgRepeatPlain;
281 
282     // There is only one variant this argument could be; put it into the argument entry.
283     arg.push_back (bp_id_arg);
284 
285     // Push the data for the first argument into the m_arguments vector.
286     m_arguments.push_back (arg);
287 }
288 
289 CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
290 {
291 }
292 
293 bool
294 CommandObjectBreakpointCommandAdd::Execute
295 (
296     Args& command,
297     CommandReturnObject &result
298 )
299 {
300     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
301 
302     if (target == NULL)
303     {
304         result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
305         result.SetStatus (eReturnStatusFailed);
306         return false;
307     }
308 
309     const BreakpointList &breakpoints = target->GetBreakpointList();
310     size_t num_breakpoints = breakpoints.GetSize();
311 
312     if (num_breakpoints == 0)
313     {
314         result.AppendError ("No breakpoints exist to have commands added");
315         result.SetStatus (eReturnStatusFailed);
316         return false;
317     }
318 
319     if (m_options.m_use_script_language == false && m_options.m_function_name.size())
320     {
321         result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
322         result.SetStatus (eReturnStatusFailed);
323         return false;
324     }
325 
326     BreakpointIDList valid_bp_ids;
327     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
328 
329     if (result.Succeeded())
330     {
331         const size_t count = valid_bp_ids.GetSize();
332         for (size_t i = 0; i < count; ++i)
333         {
334             BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
335             if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
336             {
337                 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
338                 BreakpointOptions *bp_options = NULL;
339                 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
340                 {
341                     // This breakpoint does not have an associated location.
342                     bp_options = bp->GetOptions();
343                 }
344                 else
345                 {
346                     BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
347                     // This breakpoint does have an associated location.
348                     // Get its breakpoint options.
349                     if (bp_loc_sp)
350                         bp_options = bp_loc_sp->GetLocationOptions();
351                 }
352 
353                 // Skip this breakpoint if bp_options is not good.
354                 if (bp_options == NULL) continue;
355 
356                 // If we are using script language, get the script interpreter
357                 // in order to set or collect command callback.  Otherwise, call
358                 // the methods associated with this object.
359                 if (m_options.m_use_script_language)
360                 {
361                     // Special handling for one-liner specified inline.
362                     if (m_options.m_use_one_liner)
363                     {
364                         m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
365                                                                                             m_options.m_one_liner.c_str());
366                     }
367                     // Special handling for using a Python function by name
368                     // instead of extending the breakpoint callback data structures, we just automatize
369                     // what the user would do manually: make their breakpoint command be a function call
370                     else if (m_options.m_function_name.size())
371                     {
372                         std::string oneliner(m_options.m_function_name);
373                         oneliner += "(frame, bp_loc, dict)";
374                         m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
375                                                                                             oneliner.c_str());
376                     }
377                     else
378                     {
379                         m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
380                                                                                                        result);
381                     }
382                 }
383                 else
384                 {
385                     // Special handling for one-liner specified inline.
386                     if (m_options.m_use_one_liner)
387                         SetBreakpointCommandCallback (bp_options,
388                                                       m_options.m_one_liner.c_str());
389                     else
390                         CollectDataForBreakpointCommandCallback (bp_options,
391                                                                  result);
392                 }
393             }
394         }
395     }
396 
397     return result.Succeeded();
398 }
399 
400 Options *
401 CommandObjectBreakpointCommandAdd::GetOptions ()
402 {
403     return &m_options;
404 }
405 
406 const char *g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.";
407 
408 void
409 CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
410 (
411     BreakpointOptions *bp_options,
412     CommandReturnObject &result
413 )
414 {
415     InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
416     std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
417     if (reader_sp && data_ap.get())
418     {
419         BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
420         bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
421 
422         Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
423                                           bp_options,                   // baton
424                                           eInputReaderGranularityLine,  // token size, to pass to callback function
425                                           "DONE",                       // end token
426                                           "> ",                         // prompt
427                                           true));                       // echo input
428         if (err.Success())
429         {
430             m_interpreter.GetDebugger().PushInputReader (reader_sp);
431             result.SetStatus (eReturnStatusSuccessFinishNoResult);
432         }
433         else
434         {
435             result.AppendError (err.AsCString());
436             result.SetStatus (eReturnStatusFailed);
437         }
438     }
439     else
440     {
441         result.AppendError("out of memory");
442         result.SetStatus (eReturnStatusFailed);
443     }
444 
445 }
446 
447 // Set a one-liner as the callback for the breakpoint.
448 void
449 CommandObjectBreakpointCommandAdd::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
450                                                                  const char *oneliner)
451 {
452     std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
453 
454     // It's necessary to set both user_source and script_source to the oneliner.
455     // The former is used to generate callback description (as in breakpoint command list)
456     // while the latter is used for Python to interpret during the actual callback.
457     data_ap->user_source.AppendString (oneliner);
458     data_ap->script_source.assign (oneliner);
459     data_ap->stop_on_error = m_options.m_stop_on_error;
460 
461     BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
462     bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
463 
464     return;
465 }
466 
467 size_t
468 CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
469 (
470     void *baton,
471     InputReader &reader,
472     lldb::InputReaderAction notification,
473     const char *bytes,
474     size_t bytes_len
475 )
476 {
477     StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
478     bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
479 
480     switch (notification)
481     {
482     case eInputReaderActivate:
483         if (!batch_mode)
484         {
485             out_stream->Printf ("%s\n", g_reader_instructions);
486             if (reader.GetPrompt())
487                 out_stream->Printf ("%s", reader.GetPrompt());
488             out_stream->Flush();
489         }
490         break;
491 
492     case eInputReaderDeactivate:
493         break;
494 
495     case eInputReaderReactivate:
496         if (reader.GetPrompt() && !batch_mode)
497         {
498             out_stream->Printf ("%s", reader.GetPrompt());
499             out_stream->Flush();
500         }
501         break;
502 
503     case eInputReaderAsynchronousOutputWritten:
504         break;
505 
506     case eInputReaderGotToken:
507         if (bytes && bytes_len && baton)
508         {
509             BreakpointOptions *bp_options = (BreakpointOptions *) baton;
510             if (bp_options)
511             {
512                 Baton *bp_options_baton = bp_options->GetBaton();
513                 if (bp_options_baton)
514                     ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
515             }
516         }
517         if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
518         {
519             out_stream->Printf ("%s", reader.GetPrompt());
520             out_stream->Flush();
521         }
522         break;
523 
524     case eInputReaderInterrupt:
525         {
526             // Finish, and cancel the breakpoint command.
527             reader.SetIsDone (true);
528             BreakpointOptions *bp_options = (BreakpointOptions *) baton;
529             if (bp_options)
530             {
531                 Baton *bp_options_baton = bp_options->GetBaton ();
532                 if (bp_options_baton)
533                 {
534                     ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
535                     ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
536                 }
537             }
538             if (!batch_mode)
539             {
540                 out_stream->Printf ("Warning: No command attached to breakpoint.\n");
541                 out_stream->Flush();
542             }
543         }
544         break;
545 
546     case eInputReaderEndOfFile:
547         reader.SetIsDone (true);
548         break;
549 
550     case eInputReaderDone:
551         break;
552     }
553 
554     return bytes_len;
555 }
556 
557 
558 //-------------------------------------------------------------------------
559 // CommandObjectBreakpointCommandDelete
560 //-------------------------------------------------------------------------
561 
562 CommandObjectBreakpointCommandDelete::CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
563     CommandObject (interpreter,
564                    "delete",
565                    "Delete the set of commands from a breakpoint.",
566                    NULL)
567 {
568     CommandArgumentEntry arg;
569     CommandArgumentData bp_id_arg;
570 
571     // Define the first (and only) variant of this arg.
572     bp_id_arg.arg_type = eArgTypeBreakpointID;
573     bp_id_arg.arg_repetition = eArgRepeatPlain;
574 
575     // There is only one variant this argument could be; put it into the argument entry.
576     arg.push_back (bp_id_arg);
577 
578     // Push the data for the first argument into the m_arguments vector.
579     m_arguments.push_back (arg);
580 }
581 
582 CommandObjectBreakpointCommandDelete::~CommandObjectBreakpointCommandDelete ()
583 {
584 }
585 
586 bool
587 CommandObjectBreakpointCommandDelete::Execute
588 (
589     Args& command,
590     CommandReturnObject &result
591 )
592 {
593     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
594 
595     if (target == NULL)
596     {
597         result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
598         result.SetStatus (eReturnStatusFailed);
599         return false;
600     }
601 
602     const BreakpointList &breakpoints = target->GetBreakpointList();
603     size_t num_breakpoints = breakpoints.GetSize();
604 
605     if (num_breakpoints == 0)
606     {
607         result.AppendError ("No breakpoints exist to have commands deleted");
608         result.SetStatus (eReturnStatusFailed);
609         return false;
610     }
611 
612     if (command.GetArgumentCount() == 0)
613     {
614         result.AppendError ("No breakpoint specified from which to delete the commands");
615         result.SetStatus (eReturnStatusFailed);
616         return false;
617     }
618 
619     BreakpointIDList valid_bp_ids;
620     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
621 
622     if (result.Succeeded())
623     {
624         const size_t count = valid_bp_ids.GetSize();
625         for (size_t i = 0; i < count; ++i)
626         {
627             BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
628             if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
629             {
630                 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
631                 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
632                 {
633                     BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
634                     if (bp_loc_sp)
635                         bp_loc_sp->ClearCallback();
636                     else
637                     {
638                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
639                                                      cur_bp_id.GetBreakpointID(),
640                                                      cur_bp_id.GetLocationID());
641                         result.SetStatus (eReturnStatusFailed);
642                         return false;
643                     }
644                 }
645                 else
646                 {
647                     bp->ClearCallback();
648                 }
649             }
650         }
651     }
652     return result.Succeeded();
653 }
654 
655 
656 //-------------------------------------------------------------------------
657 // CommandObjectBreakpointCommandList
658 //-------------------------------------------------------------------------
659 
660 CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
661     CommandObject (interpreter,
662                    "list",
663                    "List the script or set of commands to be executed when the breakpoint is hit.",
664                     NULL)
665 {
666     CommandArgumentEntry arg;
667     CommandArgumentData bp_id_arg;
668 
669     // Define the first (and only) variant of this arg.
670     bp_id_arg.arg_type = eArgTypeBreakpointID;
671     bp_id_arg.arg_repetition = eArgRepeatPlain;
672 
673     // There is only one variant this argument could be; put it into the argument entry.
674     arg.push_back (bp_id_arg);
675 
676     // Push the data for the first argument into the m_arguments vector.
677     m_arguments.push_back (arg);
678 }
679 
680 CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
681 {
682 }
683 
684 bool
685 CommandObjectBreakpointCommandList::Execute
686 (
687     Args& command,
688     CommandReturnObject &result
689 )
690 {
691     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
692 
693     if (target == NULL)
694     {
695         result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
696         result.SetStatus (eReturnStatusFailed);
697         return false;
698     }
699 
700     const BreakpointList &breakpoints = target->GetBreakpointList();
701     size_t num_breakpoints = breakpoints.GetSize();
702 
703     if (num_breakpoints == 0)
704     {
705         result.AppendError ("No breakpoints exist for which to list commands");
706         result.SetStatus (eReturnStatusFailed);
707         return false;
708     }
709 
710     if (command.GetArgumentCount() == 0)
711     {
712         result.AppendError ("No breakpoint specified for which to list the commands");
713         result.SetStatus (eReturnStatusFailed);
714         return false;
715     }
716 
717     BreakpointIDList valid_bp_ids;
718     CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
719 
720     if (result.Succeeded())
721     {
722         const size_t count = valid_bp_ids.GetSize();
723         for (size_t i = 0; i < count; ++i)
724         {
725             BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
726             if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
727             {
728                 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
729 
730                 if (bp)
731                 {
732                     const BreakpointOptions *bp_options = NULL;
733                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
734                     {
735                         BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
736                         if (bp_loc_sp)
737                             bp_options = bp_loc_sp->GetOptionsNoCreate();
738                         else
739                         {
740                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
741                                                          cur_bp_id.GetBreakpointID(),
742                                                          cur_bp_id.GetLocationID());
743                             result.SetStatus (eReturnStatusFailed);
744                             return false;
745                         }
746                     }
747                     else
748                     {
749                         bp_options = bp->GetOptions();
750                     }
751 
752                     if (bp_options)
753                     {
754                         StreamString id_str;
755                         BreakpointID::GetCanonicalReference (&id_str,
756                                                              cur_bp_id.GetBreakpointID(),
757                                                              cur_bp_id.GetLocationID());
758                         const Baton *baton = bp_options->GetBaton();
759                         if (baton)
760                         {
761                             result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
762                             result.GetOutputStream().IndentMore ();
763                             baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
764                             result.GetOutputStream().IndentLess ();
765                         }
766                         else
767                         {
768                             result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
769                                                             id_str.GetData());
770                         }
771                     }
772                     result.SetStatus (eReturnStatusSuccessFinishResult);
773                 }
774                 else
775                 {
776                     result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
777                     result.SetStatus (eReturnStatusFailed);
778                 }
779 
780             }
781         }
782     }
783 
784     return result.Succeeded();
785 }
786 
787 //-------------------------------------------------------------------------
788 // CommandObjectBreakpointCommand
789 //-------------------------------------------------------------------------
790 
791 CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
792     CommandObjectMultiword (interpreter,
793                             "command",
794                             "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
795                             "command <sub-command> [<sub-command-options>] <breakpoint-id>")
796 {
797     bool status;
798     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
799     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
800     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
801 
802     add_command_object->SetCommandName ("breakpoint command add");
803     delete_command_object->SetCommandName ("breakpoint command delete");
804     list_command_object->SetCommandName ("breakpoint command list");
805 
806     status = LoadSubCommand ("add",    add_command_object);
807     status = LoadSubCommand ("delete", delete_command_object);
808     status = LoadSubCommand ("list",   list_command_object);
809 }
810 
811 
812 CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
813 {
814 }
815 
816 bool
817 CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction
818 (
819     void *baton,
820     StoppointCallbackContext *context,
821     lldb::user_id_t break_id,
822     lldb::user_id_t break_loc_id
823 )
824 {
825     bool ret_value = true;
826     if (baton == NULL)
827         return true;
828 
829 
830     BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
831     StringList &commands = data->user_source;
832 
833     if (commands.GetSize() > 0)
834     {
835         ExecutionContext exe_ctx (context->exe_ctx_ref);
836         Target *target = exe_ctx.GetTargetPtr();
837         if (target)
838         {
839             CommandReturnObject result;
840             Debugger &debugger = target->GetDebugger();
841             // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
842             // if the debugger is set up that way.
843 
844             StreamSP output_stream (debugger.GetAsyncOutputStream());
845             StreamSP error_stream (debugger.GetAsyncErrorStream());
846             result.SetImmediateOutputStream (output_stream);
847             result.SetImmediateErrorStream (error_stream);
848 
849             bool stop_on_continue = true;
850             bool echo_commands    = false;
851             bool print_results    = true;
852 
853             debugger.GetCommandInterpreter().HandleCommands (commands,
854                                                              &exe_ctx,
855                                                              stop_on_continue,
856                                                              data->stop_on_error,
857                                                              echo_commands,
858                                                              print_results,
859                                                              result);
860             result.GetImmediateOutputStream()->Flush();
861             result.GetImmediateErrorStream()->Flush();
862        }
863     }
864     return ret_value;
865 }
866 
867