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