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