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