Home | History | Annotate | Download | only in Commands
      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 Your Python code, however organized, can optionally return a value.\n\
    171 If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
    172 to which the code is associated. Returning anything other than False, or even\n\
    173 returning None, or even omitting a return statement entirely, will cause\n\
    174 LLDB to stop.\n\
    175 \n\
    176 Final Note:  If you get a warning that no breakpoint command was generated, but\n\
    177 you did not get any syntax errors, you probably forgot to add a call to your\n\
    178 functions.\n\
    179 \n\
    180 Special information about debugger command breakpoint commands\n\
    181 --------------------------------------------------------------\n\
    182 \n\
    183 You may enter any debugger command, exactly as you would at the debugger prompt.\n\
    184 You may enter as many debugger commands as you like, but do NOT enter more than\n\
    185 one command per line.\n" );
    186 
    187         CommandArgumentEntry arg;
    188         CommandArgumentData bp_id_arg;
    189 
    190         // Define the first (and only) variant of this arg.
    191         bp_id_arg.arg_type = eArgTypeBreakpointID;
    192         bp_id_arg.arg_repetition = eArgRepeatPlain;
    193 
    194         // There is only one variant this argument could be; put it into the argument entry.
    195         arg.push_back (bp_id_arg);
    196 
    197         // Push the data for the first argument into the m_arguments vector.
    198         m_arguments.push_back (arg);
    199     }
    200 
    201     virtual
    202     ~CommandObjectBreakpointCommandAdd () {}
    203 
    204     virtual Options *
    205     GetOptions ()
    206     {
    207         return &m_options;
    208     }
    209 
    210     void
    211     CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
    212                                              CommandReturnObject &result)
    213     {
    214         InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger()));
    215         std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
    216         if (reader_sp && data_ap.get())
    217         {
    218             BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
    219             bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
    220 
    221             Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
    222                                               bp_options,                   // baton
    223                                               eInputReaderGranularityLine,  // token size, to pass to callback function
    224                                               "DONE",                       // end token
    225                                               "> ",                         // prompt
    226                                               true));                       // echo input
    227             if (err.Success())
    228             {
    229                 m_interpreter.GetDebugger().PushInputReader (reader_sp);
    230                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
    231             }
    232             else
    233             {
    234                 result.AppendError (err.AsCString());
    235                 result.SetStatus (eReturnStatusFailed);
    236             }
    237         }
    238         else
    239         {
    240             result.AppendError("out of memory");
    241             result.SetStatus (eReturnStatusFailed);
    242         }
    243 
    244     }
    245 
    246     /// Set a one-liner as the callback for the breakpoint.
    247     void
    248     SetBreakpointCommandCallback (BreakpointOptions *bp_options,
    249                                   const char *oneliner)
    250     {
    251         std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
    252 
    253         // It's necessary to set both user_source and script_source to the oneliner.
    254         // The former is used to generate callback description (as in breakpoint command list)
    255         // while the latter is used for Python to interpret during the actual callback.
    256         data_ap->user_source.AppendString (oneliner);
    257         data_ap->script_source.assign (oneliner);
    258         data_ap->stop_on_error = m_options.m_stop_on_error;
    259 
    260         BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
    261         bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
    262 
    263         return;
    264     }
    265 
    266     static size_t
    267     GenerateBreakpointCommandCallback (void *baton,
    268                                        InputReader &reader,
    269                                        lldb::InputReaderAction notification,
    270                                        const char *bytes,
    271                                        size_t bytes_len)
    272     {
    273         StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
    274         bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
    275 
    276         switch (notification)
    277         {
    278         case eInputReaderActivate:
    279             if (!batch_mode)
    280             {
    281                 out_stream->Printf ("%s\n", g_reader_instructions);
    282                 if (reader.GetPrompt())
    283                     out_stream->Printf ("%s", reader.GetPrompt());
    284                 out_stream->Flush();
    285             }
    286             break;
    287 
    288         case eInputReaderDeactivate:
    289             break;
    290 
    291         case eInputReaderReactivate:
    292             if (reader.GetPrompt() && !batch_mode)
    293             {
    294                 out_stream->Printf ("%s", reader.GetPrompt());
    295                 out_stream->Flush();
    296             }
    297             break;
    298 
    299         case eInputReaderAsynchronousOutputWritten:
    300             break;
    301 
    302         case eInputReaderGotToken:
    303             if (bytes && bytes_len && baton)
    304             {
    305                 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
    306                 if (bp_options)
    307                 {
    308                     Baton *bp_options_baton = bp_options->GetBaton();
    309                     if (bp_options_baton)
    310                         ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
    311                 }
    312             }
    313             if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
    314             {
    315                 out_stream->Printf ("%s", reader.GetPrompt());
    316                 out_stream->Flush();
    317             }
    318             break;
    319 
    320         case eInputReaderInterrupt:
    321             {
    322                 // Finish, and cancel the breakpoint command.
    323                 reader.SetIsDone (true);
    324                 BreakpointOptions *bp_options = (BreakpointOptions *) baton;
    325                 if (bp_options)
    326                 {
    327                     Baton *bp_options_baton = bp_options->GetBaton ();
    328                     if (bp_options_baton)
    329                     {
    330                         ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->user_source.Clear();
    331                         ((BreakpointOptions::CommandData *) bp_options_baton->m_data)->script_source.clear();
    332                     }
    333                 }
    334                 if (!batch_mode)
    335                 {
    336                     out_stream->Printf ("Warning: No command attached to breakpoint.\n");
    337                     out_stream->Flush();
    338                 }
    339             }
    340             break;
    341 
    342         case eInputReaderEndOfFile:
    343             reader.SetIsDone (true);
    344             break;
    345 
    346         case eInputReaderDone:
    347             break;
    348         }
    349 
    350         return bytes_len;
    351     }
    352 
    353     static bool
    354     BreakpointOptionsCallbackFunction (void *baton,
    355                                        StoppointCallbackContext *context,
    356                                        lldb::user_id_t break_id,
    357                                        lldb::user_id_t break_loc_id)
    358     {
    359         bool ret_value = true;
    360         if (baton == NULL)
    361             return true;
    362 
    363 
    364         BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
    365         StringList &commands = data->user_source;
    366 
    367         if (commands.GetSize() > 0)
    368         {
    369             ExecutionContext exe_ctx (context->exe_ctx_ref);
    370             Target *target = exe_ctx.GetTargetPtr();
    371             if (target)
    372             {
    373                 CommandReturnObject result;
    374                 Debugger &debugger = target->GetDebugger();
    375                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
    376                 // if the debugger is set up that way.
    377 
    378                 StreamSP output_stream (debugger.GetAsyncOutputStream());
    379                 StreamSP error_stream (debugger.GetAsyncErrorStream());
    380                 result.SetImmediateOutputStream (output_stream);
    381                 result.SetImmediateErrorStream (error_stream);
    382 
    383                 bool stop_on_continue = true;
    384                 bool echo_commands    = false;
    385                 bool print_results    = true;
    386 
    387                 debugger.GetCommandInterpreter().HandleCommands (commands,
    388                                                                  &exe_ctx,
    389                                                                  stop_on_continue,
    390                                                                  data->stop_on_error,
    391                                                                  echo_commands,
    392                                                                  print_results,
    393                                                                  eLazyBoolNo,
    394                                                                  result);
    395                 result.GetImmediateOutputStream()->Flush();
    396                 result.GetImmediateErrorStream()->Flush();
    397            }
    398         }
    399         return ret_value;
    400     }
    401 
    402     class CommandOptions : public Options
    403     {
    404     public:
    405 
    406         CommandOptions (CommandInterpreter &interpreter) :
    407             Options (interpreter),
    408             m_use_commands (false),
    409             m_use_script_language (false),
    410             m_script_language (eScriptLanguageNone),
    411             m_use_one_liner (false),
    412             m_one_liner(),
    413             m_function_name()
    414         {
    415         }
    416 
    417         virtual
    418         ~CommandOptions () {}
    419 
    420         virtual Error
    421         SetOptionValue (uint32_t option_idx, const char *option_arg)
    422         {
    423             Error error;
    424             const int short_option = m_getopt_table[option_idx].val;
    425 
    426             switch (short_option)
    427             {
    428             case 'o':
    429                 m_use_one_liner = true;
    430                 m_one_liner = option_arg;
    431                 break;
    432 
    433             case 's':
    434                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
    435                                                                                      g_option_table[option_idx].enum_values,
    436                                                                                      eScriptLanguageNone,
    437                                                                                      error);
    438 
    439                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
    440                 {
    441                     m_use_script_language = true;
    442                 }
    443                 else
    444                 {
    445                     m_use_script_language = false;
    446                 }
    447                 break;
    448 
    449             case 'e':
    450                 {
    451                     bool success = false;
    452                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
    453                     if (!success)
    454                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
    455                 }
    456                 break;
    457 
    458             case 'F':
    459                 {
    460                     m_use_one_liner = false;
    461                     m_use_script_language = true;
    462                     m_function_name.assign(option_arg);
    463                 }
    464                 break;
    465 
    466             default:
    467                 break;
    468             }
    469             return error;
    470         }
    471         void
    472         OptionParsingStarting ()
    473         {
    474             m_use_commands = true;
    475             m_use_script_language = false;
    476             m_script_language = eScriptLanguageNone;
    477 
    478             m_use_one_liner = false;
    479             m_stop_on_error = true;
    480             m_one_liner.clear();
    481             m_function_name.clear();
    482         }
    483 
    484         const OptionDefinition*
    485         GetDefinitions ()
    486         {
    487             return g_option_table;
    488         }
    489 
    490         // Options table: Required for subclasses of Options.
    491 
    492         static OptionDefinition g_option_table[];
    493 
    494         // Instance variables to hold the values for command options.
    495 
    496         bool m_use_commands;
    497         bool m_use_script_language;
    498         lldb::ScriptLanguage m_script_language;
    499 
    500         // Instance variables to hold the values for one_liner options.
    501         bool m_use_one_liner;
    502         std::string m_one_liner;
    503         bool m_stop_on_error;
    504         std::string m_function_name;
    505     };
    506 
    507 protected:
    508     virtual bool
    509     DoExecute (Args& command, CommandReturnObject &result)
    510     {
    511         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    512 
    513         if (target == NULL)
    514         {
    515             result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
    516             result.SetStatus (eReturnStatusFailed);
    517             return false;
    518         }
    519 
    520         const BreakpointList &breakpoints = target->GetBreakpointList();
    521         size_t num_breakpoints = breakpoints.GetSize();
    522 
    523         if (num_breakpoints == 0)
    524         {
    525             result.AppendError ("No breakpoints exist to have commands added");
    526             result.SetStatus (eReturnStatusFailed);
    527             return false;
    528         }
    529 
    530         if (m_options.m_use_script_language == false && m_options.m_function_name.size())
    531         {
    532             result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
    533             result.SetStatus (eReturnStatusFailed);
    534             return false;
    535         }
    536 
    537         BreakpointIDList valid_bp_ids;
    538         CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
    539 
    540         if (result.Succeeded())
    541         {
    542             const size_t count = valid_bp_ids.GetSize();
    543             if (count > 1)
    544             {
    545                 result.AppendError ("can only add commands to one breakpoint at a time.");
    546                 result.SetStatus (eReturnStatusFailed);
    547                 return false;
    548             }
    549 
    550             for (size_t i = 0; i < count; ++i)
    551             {
    552                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
    553                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
    554                 {
    555                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
    556                     BreakpointOptions *bp_options = NULL;
    557                     if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
    558                     {
    559                         // This breakpoint does not have an associated location.
    560                         bp_options = bp->GetOptions();
    561                     }
    562                     else
    563                     {
    564                         BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
    565                         // This breakpoint does have an associated location.
    566                         // Get its breakpoint options.
    567                         if (bp_loc_sp)
    568                             bp_options = bp_loc_sp->GetLocationOptions();
    569                     }
    570 
    571                     // Skip this breakpoint if bp_options is not good.
    572                     if (bp_options == NULL) continue;
    573 
    574                     // If we are using script language, get the script interpreter
    575                     // in order to set or collect command callback.  Otherwise, call
    576                     // the methods associated with this object.
    577                     if (m_options.m_use_script_language)
    578                     {
    579                         // Special handling for one-liner specified inline.
    580                         if (m_options.m_use_one_liner)
    581                         {
    582                             m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
    583                                                                                                 m_options.m_one_liner.c_str());
    584                         }
    585                         // Special handling for using a Python function by name
    586                         // instead of extending the breakpoint callback data structures, we just automatize
    587                         // what the user would do manually: make their breakpoint command be a function call
    588                         else if (m_options.m_function_name.size())
    589                         {
    590                             std::string oneliner("return ");
    591                             oneliner += m_options.m_function_name;
    592                             oneliner += "(frame, bp_loc, internal_dict)";
    593                             m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
    594                                                                                                 oneliner.c_str());
    595                         }
    596                         else
    597                         {
    598                             m_interpreter.GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_options,
    599                                                                                                            result);
    600                         }
    601                     }
    602                     else
    603                     {
    604                         // Special handling for one-liner specified inline.
    605                         if (m_options.m_use_one_liner)
    606                             SetBreakpointCommandCallback (bp_options,
    607                                                           m_options.m_one_liner.c_str());
    608                         else
    609                             CollectDataForBreakpointCommandCallback (bp_options,
    610                                                                      result);
    611                     }
    612                 }
    613             }
    614         }
    615 
    616         return result.Succeeded();
    617     }
    618 
    619 private:
    620     CommandOptions m_options;
    621     static const char *g_reader_instructions;
    622 
    623 };
    624 
    625 const char *
    626 CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.";
    627 
    628 // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
    629 // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
    630 
    631 static OptionEnumValueElement
    632 g_script_option_enumeration[4] =
    633 {
    634     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
    635     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
    636     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
    637     { 0,                      NULL,              NULL }
    638 };
    639 
    640 OptionDefinition
    641 CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
    642 {
    643     { LLDB_OPT_SET_1, false, "one-liner", 'o', required_argument, NULL, 0, eArgTypeOneLiner,
    644         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
    645 
    646     { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', required_argument, NULL, 0, eArgTypeBoolean,
    647         "Specify whether breakpoint command execution should terminate on error." },
    648 
    649     { LLDB_OPT_SET_ALL,   false, "script-type",     's', required_argument, g_script_option_enumeration, 0, eArgTypeNone,
    650         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
    651 
    652     { LLDB_OPT_SET_2,   false, "python-function",     'F', required_argument, NULL, 0, eArgTypePythonFunction,
    653         "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
    654 
    655     { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
    656 };
    657 
    658 //-------------------------------------------------------------------------
    659 // CommandObjectBreakpointCommandDelete
    660 //-------------------------------------------------------------------------
    661 
    662 class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
    663 {
    664 public:
    665     CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
    666         CommandObjectParsed (interpreter,
    667                              "delete",
    668                              "Delete the set of commands from a breakpoint.",
    669                              NULL)
    670     {
    671         CommandArgumentEntry arg;
    672         CommandArgumentData bp_id_arg;
    673 
    674         // Define the first (and only) variant of this arg.
    675         bp_id_arg.arg_type = eArgTypeBreakpointID;
    676         bp_id_arg.arg_repetition = eArgRepeatPlain;
    677 
    678         // There is only one variant this argument could be; put it into the argument entry.
    679         arg.push_back (bp_id_arg);
    680 
    681         // Push the data for the first argument into the m_arguments vector.
    682         m_arguments.push_back (arg);
    683     }
    684 
    685 
    686     virtual
    687     ~CommandObjectBreakpointCommandDelete () {}
    688 
    689 protected:
    690     virtual bool
    691     DoExecute (Args& command, CommandReturnObject &result)
    692     {
    693         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    694 
    695         if (target == NULL)
    696         {
    697             result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
    698             result.SetStatus (eReturnStatusFailed);
    699             return false;
    700         }
    701 
    702         const BreakpointList &breakpoints = target->GetBreakpointList();
    703         size_t num_breakpoints = breakpoints.GetSize();
    704 
    705         if (num_breakpoints == 0)
    706         {
    707             result.AppendError ("No breakpoints exist to have commands deleted");
    708             result.SetStatus (eReturnStatusFailed);
    709             return false;
    710         }
    711 
    712         if (command.GetArgumentCount() == 0)
    713         {
    714             result.AppendError ("No breakpoint specified from which to delete the commands");
    715             result.SetStatus (eReturnStatusFailed);
    716             return false;
    717         }
    718 
    719         BreakpointIDList valid_bp_ids;
    720         CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
    721 
    722         if (result.Succeeded())
    723         {
    724             const size_t count = valid_bp_ids.GetSize();
    725             for (size_t i = 0; i < count; ++i)
    726             {
    727                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
    728                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
    729                 {
    730                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
    731                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
    732                     {
    733                         BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
    734                         if (bp_loc_sp)
    735                             bp_loc_sp->ClearCallback();
    736                         else
    737                         {
    738                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
    739                                                          cur_bp_id.GetBreakpointID(),
    740                                                          cur_bp_id.GetLocationID());
    741                             result.SetStatus (eReturnStatusFailed);
    742                             return false;
    743                         }
    744                     }
    745                     else
    746                     {
    747                         bp->ClearCallback();
    748                     }
    749                 }
    750             }
    751         }
    752         return result.Succeeded();
    753     }
    754 };
    755 
    756 //-------------------------------------------------------------------------
    757 // CommandObjectBreakpointCommandList
    758 //-------------------------------------------------------------------------
    759 
    760 class CommandObjectBreakpointCommandList : public CommandObjectParsed
    761 {
    762 public:
    763     CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
    764         CommandObjectParsed (interpreter,
    765                              "list",
    766                              "List the script or set of commands to be executed when the breakpoint is hit.",
    767                               NULL)
    768     {
    769         CommandArgumentEntry arg;
    770         CommandArgumentData bp_id_arg;
    771 
    772         // Define the first (and only) variant of this arg.
    773         bp_id_arg.arg_type = eArgTypeBreakpointID;
    774         bp_id_arg.arg_repetition = eArgRepeatPlain;
    775 
    776         // There is only one variant this argument could be; put it into the argument entry.
    777         arg.push_back (bp_id_arg);
    778 
    779         // Push the data for the first argument into the m_arguments vector.
    780         m_arguments.push_back (arg);
    781     }
    782 
    783     virtual
    784     ~CommandObjectBreakpointCommandList () {}
    785 
    786 protected:
    787     virtual bool
    788     DoExecute (Args& command,
    789              CommandReturnObject &result)
    790     {
    791         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
    792 
    793         if (target == NULL)
    794         {
    795             result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
    796             result.SetStatus (eReturnStatusFailed);
    797             return false;
    798         }
    799 
    800         const BreakpointList &breakpoints = target->GetBreakpointList();
    801         size_t num_breakpoints = breakpoints.GetSize();
    802 
    803         if (num_breakpoints == 0)
    804         {
    805             result.AppendError ("No breakpoints exist for which to list commands");
    806             result.SetStatus (eReturnStatusFailed);
    807             return false;
    808         }
    809 
    810         if (command.GetArgumentCount() == 0)
    811         {
    812             result.AppendError ("No breakpoint specified for which to list the commands");
    813             result.SetStatus (eReturnStatusFailed);
    814             return false;
    815         }
    816 
    817         BreakpointIDList valid_bp_ids;
    818         CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
    819 
    820         if (result.Succeeded())
    821         {
    822             const size_t count = valid_bp_ids.GetSize();
    823             for (size_t i = 0; i < count; ++i)
    824             {
    825                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
    826                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
    827                 {
    828                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
    829 
    830                     if (bp)
    831                     {
    832                         const BreakpointOptions *bp_options = NULL;
    833                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
    834                         {
    835                             BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
    836                             if (bp_loc_sp)
    837                                 bp_options = bp_loc_sp->GetOptionsNoCreate();
    838                             else
    839                             {
    840                                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
    841                                                              cur_bp_id.GetBreakpointID(),
    842                                                              cur_bp_id.GetLocationID());
    843                                 result.SetStatus (eReturnStatusFailed);
    844                                 return false;
    845                             }
    846                         }
    847                         else
    848                         {
    849                             bp_options = bp->GetOptions();
    850                         }
    851 
    852                         if (bp_options)
    853                         {
    854                             StreamString id_str;
    855                             BreakpointID::GetCanonicalReference (&id_str,
    856                                                                  cur_bp_id.GetBreakpointID(),
    857                                                                  cur_bp_id.GetLocationID());
    858                             const Baton *baton = bp_options->GetBaton();
    859                             if (baton)
    860                             {
    861                                 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
    862                                 result.GetOutputStream().IndentMore ();
    863                                 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
    864                                 result.GetOutputStream().IndentLess ();
    865                             }
    866                             else
    867                             {
    868                                 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
    869                                                                 id_str.GetData());
    870                             }
    871                         }
    872                         result.SetStatus (eReturnStatusSuccessFinishResult);
    873                     }
    874                     else
    875                     {
    876                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
    877                         result.SetStatus (eReturnStatusFailed);
    878                     }
    879 
    880                 }
    881             }
    882         }
    883 
    884         return result.Succeeded();
    885     }
    886 };
    887 
    888 //-------------------------------------------------------------------------
    889 // CommandObjectBreakpointCommand
    890 //-------------------------------------------------------------------------
    891 
    892 CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
    893     CommandObjectMultiword (interpreter,
    894                             "command",
    895                             "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
    896                             "command <sub-command> [<sub-command-options>] <breakpoint-id>")
    897 {
    898     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
    899     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
    900     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
    901 
    902     add_command_object->SetCommandName ("breakpoint command add");
    903     delete_command_object->SetCommandName ("breakpoint command delete");
    904     list_command_object->SetCommandName ("breakpoint command list");
    905 
    906     LoadSubCommand ("add",    add_command_object);
    907     LoadSubCommand ("delete", delete_command_object);
    908     LoadSubCommand ("list",   list_command_object);
    909 }
    910 
    911 CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
    912 {
    913 }
    914 
    915 
    916