130fdc8d8SChris Lattner //===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner // C Includes
1130fdc8d8SChris Lattner // C++ Includes
1230fdc8d8SChris Lattner 
1330fdc8d8SChris Lattner 
1430fdc8d8SChris Lattner #include "CommandObjectBreakpointCommand.h"
1530fdc8d8SChris Lattner #include "CommandObjectBreakpoint.h"
1630fdc8d8SChris Lattner 
1744d93782SGreg Clayton #include "lldb/Core/IOHandler.h"
1830fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
1930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
2030fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2130fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2230fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h"
2330fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
2430fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
2530fdc8d8SChris Lattner #include "lldb/Breakpoint/StoppointCallbackContext.h"
2630fdc8d8SChris Lattner #include "lldb/Core/State.h"
2730fdc8d8SChris Lattner 
2830fdc8d8SChris Lattner using namespace lldb;
2930fdc8d8SChris Lattner using namespace lldb_private;
3030fdc8d8SChris Lattner 
3130fdc8d8SChris Lattner //-------------------------------------------------------------------------
3230fdc8d8SChris Lattner // CommandObjectBreakpointCommandAdd
3330fdc8d8SChris Lattner //-------------------------------------------------------------------------
3430fdc8d8SChris Lattner 
3530fdc8d8SChris Lattner 
3644d93782SGreg Clayton class CommandObjectBreakpointCommandAdd :
3744d93782SGreg Clayton     public CommandObjectParsed,
3844d93782SGreg Clayton     public IOHandlerDelegateMultiline
395a988416SJim Ingham {
405a988416SJim Ingham public:
415a988416SJim Ingham 
425a988416SJim Ingham     CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
435a988416SJim Ingham         CommandObjectParsed (interpreter,
44a7015092SGreg Clayton                              "add",
451bb0750bSJim Ingham                              "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit."
461bb0750bSJim Ingham                              "  If no breakpoint is specified, adds the commands to the last created breakpoint.",
47eb0103f2SGreg Clayton                              NULL),
48c3d874a5SGreg Clayton         IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
49eb0103f2SGreg Clayton         m_options (interpreter)
5030fdc8d8SChris Lattner     {
5130fdc8d8SChris Lattner         SetHelpLong (
52*ea671fbdSKate Stone R"(
53*ea671fbdSKate Stone General information about entering breakpoint commands
54*ea671fbdSKate Stone ------------------------------------------------------
55*ea671fbdSKate Stone 
56*ea671fbdSKate Stone )" "This command will prompt for commands to be executed when the specified \
57*ea671fbdSKate Stone breakpoint is hit.  Each command is typed on its own line following the '> ' \
58*ea671fbdSKate Stone prompt until 'DONE' is entered." R"(
59*ea671fbdSKate Stone 
60*ea671fbdSKate Stone )" "Syntactic errors may not be detected when initially entered, and many \
61*ea671fbdSKate Stone malformed commands can silently fail when executed.  If your breakpoint commands \
62*ea671fbdSKate Stone do not appear to be executing, double-check the command syntax." R"(
63*ea671fbdSKate Stone 
64*ea671fbdSKate Stone )" "Note: You may enter any debugger command exactly as you would at the debugger \
65*ea671fbdSKate Stone prompt.  There is no limit to the number of commands supplied, but do NOT enter \
66*ea671fbdSKate Stone more than one command per line." R"(
67*ea671fbdSKate Stone 
68*ea671fbdSKate Stone Special information about PYTHON breakpoint commands
69*ea671fbdSKate Stone ----------------------------------------------------
70*ea671fbdSKate Stone 
71*ea671fbdSKate Stone )" "You may enter either one or more lines of Python, including function \
72*ea671fbdSKate Stone definitions or calls to functions that will have been imported by the time \
73*ea671fbdSKate Stone the code executes.  Single line breakpoint commands will be interpreted 'as is' \
74*ea671fbdSKate Stone when the breakpoint is hit.  Multiple lines of Python will be wrapped in a \
75*ea671fbdSKate Stone generated function, and a call to the function will be attached to the breakpoint." R"(
76*ea671fbdSKate Stone 
77*ea671fbdSKate Stone This auto-generated function is passed in three arguments:
78*ea671fbdSKate Stone 
79*ea671fbdSKate Stone     frame:  an lldb.SBFrame object for the frame which hit breakpoint.
80*ea671fbdSKate Stone 
81*ea671fbdSKate Stone     bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
82*ea671fbdSKate Stone 
83*ea671fbdSKate Stone     dict:   the python session dictionary hit.
84*ea671fbdSKate Stone 
85*ea671fbdSKate Stone )" "When specifying a python function with the --python-function option, you need \
86*ea671fbdSKate Stone to supply the function name prepended by the module name:" R"(
87*ea671fbdSKate Stone 
88*ea671fbdSKate Stone     --python-function myutils.breakpoint_callback
89*ea671fbdSKate Stone 
90*ea671fbdSKate Stone The function itself must have the following prototype:
91*ea671fbdSKate Stone 
92*ea671fbdSKate Stone def breakpoint_callback(frame, bp_loc, dict):
93*ea671fbdSKate Stone   # Your code goes here
94*ea671fbdSKate Stone 
95*ea671fbdSKate Stone )" "The arguments are the same as the arguments passed to generated functions as \
96*ea671fbdSKate Stone described above.  Note that the global variable 'lldb.frame' will NOT be updated when \
97*ea671fbdSKate Stone this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
98*ea671fbdSKate Stone can get you to the thread via frame.GetThread(), the thread can get you to the \
99*ea671fbdSKate Stone process via thread.GetProcess(), and the process can get you back to the target \
100*ea671fbdSKate Stone via process.GetTarget()." R"(
101*ea671fbdSKate Stone 
102*ea671fbdSKate Stone )" "Important Note: As Python code gets collected into functions, access to global \
103*ea671fbdSKate Stone variables requires explicit scoping using the 'global' keyword.  Be sure to use correct \
104*ea671fbdSKate Stone Python syntax, including indentation, when entering Python breakpoint commands." R"(
105*ea671fbdSKate Stone 
106*ea671fbdSKate Stone Example Python one-line breakpoint command:
107*ea671fbdSKate Stone 
108*ea671fbdSKate Stone (lldb) breakpoint command add -s python 1
109*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
110*ea671fbdSKate Stone > print "Hit this breakpoint!"
111*ea671fbdSKate Stone > DONE
112*ea671fbdSKate Stone 
113*ea671fbdSKate Stone As a convenience, this also works for a short Python one-liner:
114*ea671fbdSKate Stone 
115*ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
116*ea671fbdSKate Stone (lldb) run
117*ea671fbdSKate Stone Launching '.../a.out'  (x86_64)
118*ea671fbdSKate Stone (lldb) Fri Sep 10 12:17:45 2010
119*ea671fbdSKate Stone Process 21778 Stopped
120*ea671fbdSKate Stone * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
121*ea671fbdSKate Stone   36
122*ea671fbdSKate Stone   37   	int c(int val)
123*ea671fbdSKate Stone   38   	{
124*ea671fbdSKate Stone   39 ->	    return val + 3;
125*ea671fbdSKate Stone   40   	}
126*ea671fbdSKate Stone   41
127*ea671fbdSKate Stone   42   	int main (int argc, char const *argv[])
128*ea671fbdSKate Stone 
129*ea671fbdSKate Stone Example multiple line Python breakpoint command:
130*ea671fbdSKate Stone 
131*ea671fbdSKate Stone (lldb) breakpoint command add -s p 1
132*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
133*ea671fbdSKate Stone > global bp_count
134*ea671fbdSKate Stone > bp_count = bp_count + 1
135*ea671fbdSKate Stone > print "Hit this breakpoint " + repr(bp_count) + " times!"
136*ea671fbdSKate Stone > DONE
137*ea671fbdSKate Stone 
138*ea671fbdSKate Stone Example multiple line Python breakpoint command, using function definition:
139*ea671fbdSKate Stone 
140*ea671fbdSKate Stone (lldb) breakpoint command add -s python 1
141*ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
142*ea671fbdSKate Stone > def breakpoint_output (bp_no):
143*ea671fbdSKate Stone >     out_string = "Hit breakpoint number " + repr (bp_no)
144*ea671fbdSKate Stone >     print out_string
145*ea671fbdSKate Stone >     return True
146*ea671fbdSKate Stone > breakpoint_output (1)
147*ea671fbdSKate Stone > DONE
148*ea671fbdSKate Stone 
149*ea671fbdSKate Stone )" "In this case, since there is a reference to a global variable, \
150*ea671fbdSKate Stone 'bp_count', you will also need to make sure 'bp_count' exists and is \
151*ea671fbdSKate Stone initialized:" R"(
152*ea671fbdSKate Stone 
153*ea671fbdSKate Stone (lldb) script
154*ea671fbdSKate Stone >>> bp_count = 0
155*ea671fbdSKate Stone >>> quit()
156*ea671fbdSKate Stone 
157*ea671fbdSKate Stone )" "Your Python code, however organized, can optionally return a value.  \
158*ea671fbdSKate Stone If the returned value is False, that tells LLDB not to stop at the breakpoint \
159*ea671fbdSKate Stone to which the code is associated. Returning anything other than False, or even \
160*ea671fbdSKate Stone returning None, or even omitting a return statement entirely, will cause \
161*ea671fbdSKate Stone LLDB to stop." R"(
162*ea671fbdSKate Stone 
163*ea671fbdSKate Stone )" "Final Note: A warning that no breakpoint command was generated when there \
164*ea671fbdSKate Stone are no syntax errors may indicate that a function was declared but never called."
165*ea671fbdSKate Stone         );
166405fe67fSCaroline Tice 
167405fe67fSCaroline Tice         CommandArgumentEntry arg;
168405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
169405fe67fSCaroline Tice 
170405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
171405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
1721bb0750bSJim Ingham         bp_id_arg.arg_repetition = eArgRepeatOptional;
173405fe67fSCaroline Tice 
174405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
175405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
176405fe67fSCaroline Tice 
177405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
178405fe67fSCaroline Tice         m_arguments.push_back (arg);
17930fdc8d8SChris Lattner     }
18030fdc8d8SChris Lattner 
1815a988416SJim Ingham     virtual
1825a988416SJim Ingham     ~CommandObjectBreakpointCommandAdd () {}
1835a988416SJim Ingham 
1845a988416SJim Ingham     virtual Options *
1855a988416SJim Ingham     GetOptions ()
1865a988416SJim Ingham     {
1875a988416SJim Ingham         return &m_options;
1885a988416SJim Ingham     }
1895a988416SJim Ingham 
19044d93782SGreg Clayton     virtual void
19144d93782SGreg Clayton     IOHandlerActivated (IOHandler &io_handler)
19244d93782SGreg Clayton     {
19344d93782SGreg Clayton         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
19444d93782SGreg Clayton         if (output_sp)
19544d93782SGreg Clayton         {
19644d93782SGreg Clayton             output_sp->PutCString(g_reader_instructions);
19744d93782SGreg Clayton             output_sp->Flush();
19844d93782SGreg Clayton         }
19944d93782SGreg Clayton     }
20044d93782SGreg Clayton 
20144d93782SGreg Clayton 
20244d93782SGreg Clayton     virtual void
20344d93782SGreg Clayton     IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
20444d93782SGreg Clayton     {
20544d93782SGreg Clayton         io_handler.SetIsDone(true);
20644d93782SGreg Clayton 
207b5796cb4SJim Ingham         std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
208b5796cb4SJim Ingham         for (BreakpointOptions *bp_options : *bp_options_vec)
20944d93782SGreg Clayton         {
210b5796cb4SJim Ingham             if (!bp_options)
211b5796cb4SJim Ingham                 continue;
212b5796cb4SJim Ingham 
21344d93782SGreg Clayton             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
21444d93782SGreg Clayton             if (data_ap.get())
21544d93782SGreg Clayton             {
21644d93782SGreg Clayton                 data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
21744d93782SGreg Clayton                 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
21844d93782SGreg Clayton                 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
21944d93782SGreg Clayton             }
22044d93782SGreg Clayton         }
22144d93782SGreg Clayton     }
22244d93782SGreg Clayton 
2235a988416SJim Ingham     void
224b5796cb4SJim Ingham     CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
2255a988416SJim Ingham                                              CommandReturnObject &result)
2265a988416SJim Ingham     {
22744d93782SGreg Clayton         m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
22844d93782SGreg Clayton                                                     *this,          // IOHandlerDelegate
22944d93782SGreg Clayton                                                     true,           // Run IOHandler in async mode
230b5796cb4SJim Ingham                                                     &bp_options_vec);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
2315a988416SJim Ingham     }
2325a988416SJim Ingham 
2335a988416SJim Ingham     /// Set a one-liner as the callback for the breakpoint.
2345a988416SJim Ingham     void
235b5796cb4SJim Ingham     SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
2365a988416SJim Ingham                                   const char *oneliner)
2375a988416SJim Ingham     {
238b5796cb4SJim Ingham         for (auto bp_options : bp_options_vec)
239b5796cb4SJim Ingham         {
2407b0992d9SGreg Clayton             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
2415a988416SJim Ingham 
2425a988416SJim Ingham             // It's necessary to set both user_source and script_source to the oneliner.
2435a988416SJim Ingham             // The former is used to generate callback description (as in breakpoint command list)
2445a988416SJim Ingham             // while the latter is used for Python to interpret during the actual callback.
2455a988416SJim Ingham             data_ap->user_source.AppendString (oneliner);
2465a988416SJim Ingham             data_ap->script_source.assign (oneliner);
2475a988416SJim Ingham             data_ap->stop_on_error = m_options.m_stop_on_error;
2485a988416SJim Ingham 
2495a988416SJim Ingham             BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
2505a988416SJim Ingham             bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
251b5796cb4SJim Ingham         }
2525a988416SJim Ingham         return;
2535a988416SJim Ingham     }
2545a988416SJim Ingham 
2555a988416SJim Ingham     static bool
2565a988416SJim Ingham     BreakpointOptionsCallbackFunction (void *baton,
2575a988416SJim Ingham                                        StoppointCallbackContext *context,
2585a988416SJim Ingham                                        lldb::user_id_t break_id,
2595a988416SJim Ingham                                        lldb::user_id_t break_loc_id)
2605a988416SJim Ingham     {
2615a988416SJim Ingham         bool ret_value = true;
2625a988416SJim Ingham         if (baton == NULL)
2635a988416SJim Ingham             return true;
2645a988416SJim Ingham 
2655a988416SJim Ingham 
2665a988416SJim Ingham         BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
2675a988416SJim Ingham         StringList &commands = data->user_source;
2685a988416SJim Ingham 
2695a988416SJim Ingham         if (commands.GetSize() > 0)
2705a988416SJim Ingham         {
2715a988416SJim Ingham             ExecutionContext exe_ctx (context->exe_ctx_ref);
2725a988416SJim Ingham             Target *target = exe_ctx.GetTargetPtr();
2735a988416SJim Ingham             if (target)
2745a988416SJim Ingham             {
2755a988416SJim Ingham                 CommandReturnObject result;
2765a988416SJim Ingham                 Debugger &debugger = target->GetDebugger();
2775a988416SJim Ingham                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
2785a988416SJim Ingham                 // if the debugger is set up that way.
2795a988416SJim Ingham 
2805a988416SJim Ingham                 StreamSP output_stream (debugger.GetAsyncOutputStream());
2815a988416SJim Ingham                 StreamSP error_stream (debugger.GetAsyncErrorStream());
2825a988416SJim Ingham                 result.SetImmediateOutputStream (output_stream);
2835a988416SJim Ingham                 result.SetImmediateErrorStream (error_stream);
2845a988416SJim Ingham 
28526c7bf93SJim Ingham                 CommandInterpreterRunOptions options;
28626c7bf93SJim Ingham                 options.SetStopOnContinue(true);
28726c7bf93SJim Ingham                 options.SetStopOnError (data->stop_on_error);
28826c7bf93SJim Ingham                 options.SetEchoCommands (true);
28926c7bf93SJim Ingham                 options.SetPrintResults (true);
29026c7bf93SJim Ingham                 options.SetAddToHistory (false);
2915a988416SJim Ingham 
2925a988416SJim Ingham                 debugger.GetCommandInterpreter().HandleCommands (commands,
2935a988416SJim Ingham                                                                  &exe_ctx,
29426c7bf93SJim Ingham                                                                  options,
2955a988416SJim Ingham                                                                  result);
2965a988416SJim Ingham                 result.GetImmediateOutputStream()->Flush();
2975a988416SJim Ingham                 result.GetImmediateErrorStream()->Flush();
2985a988416SJim Ingham            }
2995a988416SJim Ingham         }
3005a988416SJim Ingham         return ret_value;
3015a988416SJim Ingham     }
3025a988416SJim Ingham 
3035a988416SJim Ingham     class CommandOptions : public Options
3045a988416SJim Ingham     {
3055a988416SJim Ingham     public:
3065a988416SJim Ingham 
3075a988416SJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
3085a988416SJim Ingham             Options (interpreter),
3095a988416SJim Ingham             m_use_commands (false),
3105a988416SJim Ingham             m_use_script_language (false),
3115a988416SJim Ingham             m_script_language (eScriptLanguageNone),
3125a988416SJim Ingham             m_use_one_liner (false),
3135a988416SJim Ingham             m_one_liner(),
3145a988416SJim Ingham             m_function_name()
31530fdc8d8SChris Lattner         {
31630fdc8d8SChris Lattner         }
31730fdc8d8SChris Lattner 
3185a988416SJim Ingham         virtual
3195a988416SJim Ingham         ~CommandOptions () {}
3205a988416SJim Ingham 
3215a988416SJim Ingham         virtual Error
3225a988416SJim Ingham         SetOptionValue (uint32_t option_idx, const char *option_arg)
3235a988416SJim Ingham         {
3245a988416SJim Ingham             Error error;
3253bcdfc0eSGreg Clayton             const int short_option = m_getopt_table[option_idx].val;
3265a988416SJim Ingham 
3275a988416SJim Ingham             switch (short_option)
3285a988416SJim Ingham             {
3295a988416SJim Ingham             case 'o':
3305a988416SJim Ingham                 m_use_one_liner = true;
3315a988416SJim Ingham                 m_one_liner = option_arg;
3325a988416SJim Ingham                 break;
3335a988416SJim Ingham 
3345a988416SJim Ingham             case 's':
3355a988416SJim Ingham                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
3365a988416SJim Ingham                                                                                      g_option_table[option_idx].enum_values,
3375a988416SJim Ingham                                                                                      eScriptLanguageNone,
3385a988416SJim Ingham                                                                                      error);
3395a988416SJim Ingham 
3405a988416SJim Ingham                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
3415a988416SJim Ingham                 {
3425a988416SJim Ingham                     m_use_script_language = true;
3435a988416SJim Ingham                 }
3445a988416SJim Ingham                 else
3455a988416SJim Ingham                 {
3465a988416SJim Ingham                     m_use_script_language = false;
3475a988416SJim Ingham                 }
3485a988416SJim Ingham                 break;
3495a988416SJim Ingham 
3505a988416SJim Ingham             case 'e':
3515a988416SJim Ingham                 {
3525a988416SJim Ingham                     bool success = false;
3535a988416SJim Ingham                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
3545a988416SJim Ingham                     if (!success)
3555a988416SJim Ingham                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
3565a988416SJim Ingham                 }
3575a988416SJim Ingham                 break;
3585a988416SJim Ingham 
3595a988416SJim Ingham             case 'F':
3605a988416SJim Ingham                 {
3615a988416SJim Ingham                     m_use_one_liner = false;
3625a988416SJim Ingham                     m_use_script_language = true;
3635a988416SJim Ingham                     m_function_name.assign(option_arg);
3645a988416SJim Ingham                 }
3655a988416SJim Ingham                 break;
3665a988416SJim Ingham 
36733df7cd3SJim Ingham             case 'D':
36833df7cd3SJim Ingham                 m_use_dummy = true;
36933df7cd3SJim Ingham                 break;
37033df7cd3SJim Ingham 
3715a988416SJim Ingham             default:
3725a988416SJim Ingham                 break;
3735a988416SJim Ingham             }
3745a988416SJim Ingham             return error;
3755a988416SJim Ingham         }
3765a988416SJim Ingham         void
3775a988416SJim Ingham         OptionParsingStarting ()
3785a988416SJim Ingham         {
3795a988416SJim Ingham             m_use_commands = true;
3805a988416SJim Ingham             m_use_script_language = false;
3815a988416SJim Ingham             m_script_language = eScriptLanguageNone;
3825a988416SJim Ingham 
3835a988416SJim Ingham             m_use_one_liner = false;
3845a988416SJim Ingham             m_stop_on_error = true;
3855a988416SJim Ingham             m_one_liner.clear();
3865a988416SJim Ingham             m_function_name.clear();
38733df7cd3SJim Ingham             m_use_dummy = false;
3885a988416SJim Ingham         }
3895a988416SJim Ingham 
3905a988416SJim Ingham         const OptionDefinition*
3915a988416SJim Ingham         GetDefinitions ()
3925a988416SJim Ingham         {
3935a988416SJim Ingham             return g_option_table;
3945a988416SJim Ingham         }
3955a988416SJim Ingham 
3965a988416SJim Ingham         // Options table: Required for subclasses of Options.
3975a988416SJim Ingham 
3985a988416SJim Ingham         static OptionDefinition g_option_table[];
3995a988416SJim Ingham 
4005a988416SJim Ingham         // Instance variables to hold the values for command options.
4015a988416SJim Ingham 
4025a988416SJim Ingham         bool m_use_commands;
4035a988416SJim Ingham         bool m_use_script_language;
4045a988416SJim Ingham         lldb::ScriptLanguage m_script_language;
4055a988416SJim Ingham 
4065a988416SJim Ingham         // Instance variables to hold the values for one_liner options.
4075a988416SJim Ingham         bool m_use_one_liner;
4085a988416SJim Ingham         std::string m_one_liner;
4095a988416SJim Ingham         bool m_stop_on_error;
4105a988416SJim Ingham         std::string m_function_name;
41133df7cd3SJim Ingham         bool m_use_dummy;
4125a988416SJim Ingham     };
4135a988416SJim Ingham 
4145a988416SJim Ingham protected:
4155a988416SJim Ingham     virtual bool
4165a988416SJim Ingham     DoExecute (Args& command, CommandReturnObject &result)
41730fdc8d8SChris Lattner     {
41833df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
41930fdc8d8SChris Lattner 
42030fdc8d8SChris Lattner         if (target == NULL)
42130fdc8d8SChris Lattner         {
42230fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
42330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
42430fdc8d8SChris Lattner             return false;
42530fdc8d8SChris Lattner         }
42630fdc8d8SChris Lattner 
42730fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
42830fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
42930fdc8d8SChris Lattner 
43030fdc8d8SChris Lattner         if (num_breakpoints == 0)
43130fdc8d8SChris Lattner         {
43230fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist to have commands added");
43330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
43430fdc8d8SChris Lattner             return false;
43530fdc8d8SChris Lattner         }
43630fdc8d8SChris Lattner 
4378d4a8010SEnrico Granata         if (m_options.m_use_script_language == false && m_options.m_function_name.size())
4388d4a8010SEnrico Granata         {
4398d4a8010SEnrico Granata             result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
4408d4a8010SEnrico Granata             result.SetStatus (eReturnStatusFailed);
4418d4a8010SEnrico Granata             return false;
4428d4a8010SEnrico Granata         }
4438d4a8010SEnrico Granata 
44430fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
4455e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
44630fdc8d8SChris Lattner 
447b5796cb4SJim Ingham         m_bp_options_vec.clear();
448b5796cb4SJim Ingham 
44930fdc8d8SChris Lattner         if (result.Succeeded())
45030fdc8d8SChris Lattner         {
451c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
452d9916eaeSJim Ingham 
453c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
45430fdc8d8SChris Lattner             {
45530fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
45630fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
45730fdc8d8SChris Lattner                 {
45830fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
45939d7d4f0SJohnny Chen                     BreakpointOptions *bp_options = NULL;
46039d7d4f0SJohnny Chen                     if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
46139d7d4f0SJohnny Chen                     {
46239d7d4f0SJohnny Chen                         // This breakpoint does not have an associated location.
46339d7d4f0SJohnny Chen                         bp_options = bp->GetOptions();
46439d7d4f0SJohnny Chen                     }
46539d7d4f0SJohnny Chen                     else
46630fdc8d8SChris Lattner                     {
46730fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
46839d7d4f0SJohnny Chen                         // This breakpoint does have an associated location.
46939d7d4f0SJohnny Chen                         // Get its breakpoint options.
47030fdc8d8SChris Lattner                         if (bp_loc_sp)
47139d7d4f0SJohnny Chen                             bp_options = bp_loc_sp->GetLocationOptions();
47239d7d4f0SJohnny Chen                     }
473b5796cb4SJim Ingham                     if (bp_options)
474b5796cb4SJim Ingham                         m_bp_options_vec.push_back (bp_options);
475b5796cb4SJim Ingham                 }
476b5796cb4SJim Ingham             }
47739d7d4f0SJohnny Chen 
47839d7d4f0SJohnny Chen             // If we are using script language, get the script interpreter
47939d7d4f0SJohnny Chen             // in order to set or collect command callback.  Otherwise, call
48039d7d4f0SJohnny Chen             // the methods associated with this object.
48130fdc8d8SChris Lattner             if (m_options.m_use_script_language)
48230fdc8d8SChris Lattner             {
483b5796cb4SJim Ingham                 ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
48439d7d4f0SJohnny Chen                 // Special handling for one-liner specified inline.
48539d7d4f0SJohnny Chen                 if (m_options.m_use_one_liner)
4868d4a8010SEnrico Granata                 {
487b5796cb4SJim Ingham                     script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
48839d7d4f0SJohnny Chen                                                                  m_options.m_one_liner.c_str());
4898d4a8010SEnrico Granata                 }
4908d4a8010SEnrico Granata                 else if (m_options.m_function_name.size())
4918d4a8010SEnrico Granata                 {
492b5796cb4SJim Ingham                     script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
493d80102e4SJim Ingham                                                                          m_options.m_function_name.c_str());
4948d4a8010SEnrico Granata                 }
49594de55d5SJohnny Chen                 else
4968d4a8010SEnrico Granata                 {
497b5796cb4SJim Ingham                     script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
49830fdc8d8SChris Lattner                                                                             result);
49930fdc8d8SChris Lattner                 }
5008d4a8010SEnrico Granata             }
50130fdc8d8SChris Lattner             else
50230fdc8d8SChris Lattner             {
50339d7d4f0SJohnny Chen                 // Special handling for one-liner specified inline.
50439d7d4f0SJohnny Chen                 if (m_options.m_use_one_liner)
505b5796cb4SJim Ingham                     SetBreakpointCommandCallback (m_bp_options_vec,
50639d7d4f0SJohnny Chen                                                   m_options.m_one_liner.c_str());
50739d7d4f0SJohnny Chen                 else
508b5796cb4SJim Ingham                     CollectDataForBreakpointCommandCallback (m_bp_options_vec,
509b132097bSGreg Clayton                                                              result);
51030fdc8d8SChris Lattner             }
511b5796cb4SJim Ingham 
51230fdc8d8SChris Lattner         }
51330fdc8d8SChris Lattner 
51430fdc8d8SChris Lattner         return result.Succeeded();
51530fdc8d8SChris Lattner     }
51630fdc8d8SChris Lattner 
5175a988416SJim Ingham private:
5185a988416SJim Ingham     CommandOptions m_options;
519b5796cb4SJim Ingham     std::vector<BreakpointOptions *> m_bp_options_vec;  // This stores the breakpoint options that we are currently
520b5796cb4SJim Ingham                                                         // collecting commands for.  In the CollectData... calls we need
521b5796cb4SJim Ingham                                                         // to hand this off to the IOHandler, which may run asynchronously.
522b5796cb4SJim Ingham                                                         // So we have to have some way to keep it alive, and not leak it.
523b5796cb4SJim Ingham                                                         // Making it an ivar of the command object, which never goes away
524b5796cb4SJim Ingham                                                         // achieves this.  Note that if we were able to run
525b5796cb4SJim Ingham                                                         // the same command concurrently in one interpreter we'd have to
526b5796cb4SJim Ingham                                                         // make this "per invocation".  But there are many more reasons
527b5796cb4SJim Ingham                                                         // why it is not in general safe to do that in lldb at present,
528b5796cb4SJim Ingham                                                         // so it isn't worthwhile to come up with a more complex mechanism
529b5796cb4SJim Ingham                                                         // to address this particular weakness right now.
5305a988416SJim Ingham     static const char *g_reader_instructions;
5315a988416SJim Ingham 
5325a988416SJim Ingham };
5335a988416SJim Ingham 
5345a988416SJim Ingham const char *
53544d93782SGreg Clayton CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.\n";
5365a988416SJim Ingham 
5375a988416SJim Ingham // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
5385a988416SJim Ingham // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
5395a988416SJim Ingham 
5405a988416SJim Ingham static OptionEnumValueElement
5415a988416SJim Ingham g_script_option_enumeration[4] =
54230fdc8d8SChris Lattner {
5435a988416SJim Ingham     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
5445a988416SJim Ingham     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
5455a988416SJim Ingham     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
5465a988416SJim Ingham     { 0,                      NULL,              NULL }
5475a988416SJim Ingham };
54830fdc8d8SChris Lattner 
5495a988416SJim Ingham OptionDefinition
5505a988416SJim Ingham CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
55130fdc8d8SChris Lattner {
552d37221dcSZachary Turner     { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
5535a988416SJim Ingham         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
55430fdc8d8SChris Lattner 
555d37221dcSZachary Turner     { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
5565a988416SJim Ingham         "Specify whether breakpoint command execution should terminate on error." },
55730fdc8d8SChris Lattner 
558d37221dcSZachary Turner     { LLDB_OPT_SET_ALL,   false, "script-type",     's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
5595a988416SJim Ingham         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
56030fdc8d8SChris Lattner 
561d37221dcSZachary Turner     { LLDB_OPT_SET_2,   false, "python-function",     'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
5625a988416SJim Ingham         "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
56339d7d4f0SJohnny Chen 
56433df7cd3SJim Ingham     { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
56533df7cd3SJim Ingham         "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
56633df7cd3SJim Ingham 
567d37221dcSZachary Turner     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
5685a988416SJim Ingham };
56930fdc8d8SChris Lattner 
57030fdc8d8SChris Lattner //-------------------------------------------------------------------------
57193e0f19fSCaroline Tice // CommandObjectBreakpointCommandDelete
57230fdc8d8SChris Lattner //-------------------------------------------------------------------------
57330fdc8d8SChris Lattner 
5745a988416SJim Ingham class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
5755a988416SJim Ingham {
5765a988416SJim Ingham public:
5775a988416SJim Ingham     CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
5785a988416SJim Ingham         CommandObjectParsed (interpreter,
57993e0f19fSCaroline Tice                              "delete",
58093e0f19fSCaroline Tice                              "Delete the set of commands from a breakpoint.",
58133df7cd3SJim Ingham                              NULL),
58233df7cd3SJim Ingham         m_options (interpreter)
58330fdc8d8SChris Lattner     {
584405fe67fSCaroline Tice         CommandArgumentEntry arg;
585405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
586405fe67fSCaroline Tice 
587405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
588405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
589405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
590405fe67fSCaroline Tice 
591405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
592405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
593405fe67fSCaroline Tice 
594405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
595405fe67fSCaroline Tice         m_arguments.push_back (arg);
59630fdc8d8SChris Lattner     }
59730fdc8d8SChris Lattner 
59830fdc8d8SChris Lattner 
5995a988416SJim Ingham     virtual
6005a988416SJim Ingham     ~CommandObjectBreakpointCommandDelete () {}
6015a988416SJim Ingham 
60233df7cd3SJim Ingham     virtual Options *
60333df7cd3SJim Ingham     GetOptions ()
60433df7cd3SJim Ingham     {
60533df7cd3SJim Ingham         return &m_options;
60633df7cd3SJim Ingham     }
60733df7cd3SJim Ingham 
60833df7cd3SJim Ingham     class CommandOptions : public Options
60933df7cd3SJim Ingham     {
61033df7cd3SJim Ingham     public:
61133df7cd3SJim Ingham 
61233df7cd3SJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
61333df7cd3SJim Ingham             Options (interpreter),
61433df7cd3SJim Ingham             m_use_dummy (false)
61533df7cd3SJim Ingham         {
61633df7cd3SJim Ingham         }
61733df7cd3SJim Ingham 
61833df7cd3SJim Ingham         virtual
61933df7cd3SJim Ingham         ~CommandOptions () {}
62033df7cd3SJim Ingham 
62133df7cd3SJim Ingham         virtual Error
62233df7cd3SJim Ingham         SetOptionValue (uint32_t option_idx, const char *option_arg)
62333df7cd3SJim Ingham         {
62433df7cd3SJim Ingham             Error error;
62533df7cd3SJim Ingham             const int short_option = m_getopt_table[option_idx].val;
62633df7cd3SJim Ingham 
62733df7cd3SJim Ingham             switch (short_option)
62833df7cd3SJim Ingham             {
62933df7cd3SJim Ingham                 case 'D':
63033df7cd3SJim Ingham                     m_use_dummy = true;
63133df7cd3SJim Ingham                     break;
63233df7cd3SJim Ingham 
63333df7cd3SJim Ingham                 default:
63433df7cd3SJim Ingham                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
63533df7cd3SJim Ingham                     break;
63633df7cd3SJim Ingham             }
63733df7cd3SJim Ingham 
63833df7cd3SJim Ingham             return error;
63933df7cd3SJim Ingham         }
64033df7cd3SJim Ingham 
64133df7cd3SJim Ingham         void
64233df7cd3SJim Ingham         OptionParsingStarting ()
64333df7cd3SJim Ingham         {
64433df7cd3SJim Ingham             m_use_dummy = false;
64533df7cd3SJim Ingham         }
64633df7cd3SJim Ingham 
64733df7cd3SJim Ingham         const OptionDefinition*
64833df7cd3SJim Ingham         GetDefinitions ()
64933df7cd3SJim Ingham         {
65033df7cd3SJim Ingham             return g_option_table;
65133df7cd3SJim Ingham         }
65233df7cd3SJim Ingham 
65333df7cd3SJim Ingham         // Options table: Required for subclasses of Options.
65433df7cd3SJim Ingham 
65533df7cd3SJim Ingham         static OptionDefinition g_option_table[];
65633df7cd3SJim Ingham 
65733df7cd3SJim Ingham         // Instance variables to hold the values for command options.
65833df7cd3SJim Ingham         bool m_use_dummy;
65933df7cd3SJim Ingham     };
66033df7cd3SJim Ingham 
6615a988416SJim Ingham protected:
6625a988416SJim Ingham     virtual bool
6635a988416SJim Ingham     DoExecute (Args& command, CommandReturnObject &result)
66430fdc8d8SChris Lattner     {
66533df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
66630fdc8d8SChris Lattner 
66730fdc8d8SChris Lattner         if (target == NULL)
66830fdc8d8SChris Lattner         {
66993e0f19fSCaroline Tice             result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
67030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
67130fdc8d8SChris Lattner             return false;
67230fdc8d8SChris Lattner         }
67330fdc8d8SChris Lattner 
67430fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
67530fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
67630fdc8d8SChris Lattner 
67730fdc8d8SChris Lattner         if (num_breakpoints == 0)
67830fdc8d8SChris Lattner         {
67993e0f19fSCaroline Tice             result.AppendError ("No breakpoints exist to have commands deleted");
68030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
68130fdc8d8SChris Lattner             return false;
68230fdc8d8SChris Lattner         }
68330fdc8d8SChris Lattner 
68430fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
68530fdc8d8SChris Lattner         {
68693e0f19fSCaroline Tice             result.AppendError ("No breakpoint specified from which to delete the commands");
68730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
68830fdc8d8SChris Lattner             return false;
68930fdc8d8SChris Lattner         }
69030fdc8d8SChris Lattner 
69130fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
6925e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
69330fdc8d8SChris Lattner 
69430fdc8d8SChris Lattner         if (result.Succeeded())
69530fdc8d8SChris Lattner         {
696c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
697c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
69830fdc8d8SChris Lattner             {
69930fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
70030fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
70130fdc8d8SChris Lattner                 {
70230fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
70330fdc8d8SChris Lattner                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
70430fdc8d8SChris Lattner                     {
70530fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
70630fdc8d8SChris Lattner                         if (bp_loc_sp)
70730fdc8d8SChris Lattner                             bp_loc_sp->ClearCallback();
70830fdc8d8SChris Lattner                         else
70930fdc8d8SChris Lattner                         {
71030fdc8d8SChris Lattner                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
71130fdc8d8SChris Lattner                                                          cur_bp_id.GetBreakpointID(),
71230fdc8d8SChris Lattner                                                          cur_bp_id.GetLocationID());
71330fdc8d8SChris Lattner                             result.SetStatus (eReturnStatusFailed);
71430fdc8d8SChris Lattner                             return false;
71530fdc8d8SChris Lattner                         }
71630fdc8d8SChris Lattner                     }
71730fdc8d8SChris Lattner                     else
71830fdc8d8SChris Lattner                     {
71930fdc8d8SChris Lattner                         bp->ClearCallback();
72030fdc8d8SChris Lattner                     }
72130fdc8d8SChris Lattner                 }
72230fdc8d8SChris Lattner             }
72330fdc8d8SChris Lattner         }
72430fdc8d8SChris Lattner         return result.Succeeded();
72530fdc8d8SChris Lattner     }
72633df7cd3SJim Ingham private:
72733df7cd3SJim Ingham     CommandOptions m_options;
7285a988416SJim Ingham };
72930fdc8d8SChris Lattner 
73033df7cd3SJim Ingham OptionDefinition
73133df7cd3SJim Ingham CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
73233df7cd3SJim Ingham {
73333df7cd3SJim Ingham     { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
73433df7cd3SJim Ingham         "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
73533df7cd3SJim Ingham 
73633df7cd3SJim Ingham     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
73733df7cd3SJim Ingham };
73833df7cd3SJim Ingham 
73933df7cd3SJim Ingham 
74030fdc8d8SChris Lattner //-------------------------------------------------------------------------
74130fdc8d8SChris Lattner // CommandObjectBreakpointCommandList
74230fdc8d8SChris Lattner //-------------------------------------------------------------------------
74330fdc8d8SChris Lattner 
7445a988416SJim Ingham class CommandObjectBreakpointCommandList : public CommandObjectParsed
7455a988416SJim Ingham {
7465a988416SJim Ingham public:
7475a988416SJim Ingham     CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
7485a988416SJim Ingham         CommandObjectParsed (interpreter,
749a7015092SGreg Clayton                              "list",
75030fdc8d8SChris Lattner                              "List the script or set of commands to be executed when the breakpoint is hit.",
751405fe67fSCaroline Tice                               NULL)
75230fdc8d8SChris Lattner     {
753405fe67fSCaroline Tice         CommandArgumentEntry arg;
754405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
755405fe67fSCaroline Tice 
756405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
757405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
758405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
759405fe67fSCaroline Tice 
760405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
761405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
762405fe67fSCaroline Tice 
763405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
764405fe67fSCaroline Tice         m_arguments.push_back (arg);
76530fdc8d8SChris Lattner     }
76630fdc8d8SChris Lattner 
7675a988416SJim Ingham     virtual
7685a988416SJim Ingham     ~CommandObjectBreakpointCommandList () {}
76930fdc8d8SChris Lattner 
7705a988416SJim Ingham protected:
7715a988416SJim Ingham     virtual bool
7725a988416SJim Ingham     DoExecute (Args& command,
7735a988416SJim Ingham              CommandReturnObject &result)
77430fdc8d8SChris Lattner     {
775a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
77630fdc8d8SChris Lattner 
77730fdc8d8SChris Lattner         if (target == NULL)
77830fdc8d8SChris Lattner         {
77930fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
78030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
78130fdc8d8SChris Lattner             return false;
78230fdc8d8SChris Lattner         }
78330fdc8d8SChris Lattner 
78430fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
78530fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
78630fdc8d8SChris Lattner 
78730fdc8d8SChris Lattner         if (num_breakpoints == 0)
78830fdc8d8SChris Lattner         {
78930fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist for which to list commands");
79030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
79130fdc8d8SChris Lattner             return false;
79230fdc8d8SChris Lattner         }
79330fdc8d8SChris Lattner 
79430fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
79530fdc8d8SChris Lattner         {
79630fdc8d8SChris Lattner             result.AppendError ("No breakpoint specified for which to list the commands");
79730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
79830fdc8d8SChris Lattner             return false;
79930fdc8d8SChris Lattner         }
80030fdc8d8SChris Lattner 
80130fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
8025e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
80330fdc8d8SChris Lattner 
80430fdc8d8SChris Lattner         if (result.Succeeded())
80530fdc8d8SChris Lattner         {
806c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
807c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
80830fdc8d8SChris Lattner             {
80930fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
81030fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
81130fdc8d8SChris Lattner                 {
81230fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
81330fdc8d8SChris Lattner 
81430fdc8d8SChris Lattner                     if (bp)
81530fdc8d8SChris Lattner                     {
8161b54c88cSJim Ingham                         const BreakpointOptions *bp_options = NULL;
81730fdc8d8SChris Lattner                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
81830fdc8d8SChris Lattner                         {
81930fdc8d8SChris Lattner                             BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
82030fdc8d8SChris Lattner                             if (bp_loc_sp)
82105407f6bSJim Ingham                                 bp_options = bp_loc_sp->GetOptionsNoCreate();
82230fdc8d8SChris Lattner                             else
82330fdc8d8SChris Lattner                             {
82430fdc8d8SChris Lattner                                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
82530fdc8d8SChris Lattner                                                              cur_bp_id.GetBreakpointID(),
82630fdc8d8SChris Lattner                                                              cur_bp_id.GetLocationID());
82730fdc8d8SChris Lattner                                 result.SetStatus (eReturnStatusFailed);
82830fdc8d8SChris Lattner                                 return false;
82930fdc8d8SChris Lattner                             }
83030fdc8d8SChris Lattner                         }
83130fdc8d8SChris Lattner                         else
83230fdc8d8SChris Lattner                         {
83330fdc8d8SChris Lattner                             bp_options = bp->GetOptions();
83430fdc8d8SChris Lattner                         }
83530fdc8d8SChris Lattner 
83630fdc8d8SChris Lattner                         if (bp_options)
83730fdc8d8SChris Lattner                         {
83830fdc8d8SChris Lattner                             StreamString id_str;
839e16c50a1SJim Ingham                             BreakpointID::GetCanonicalReference (&id_str,
840e16c50a1SJim Ingham                                                                  cur_bp_id.GetBreakpointID(),
841e16c50a1SJim Ingham                                                                  cur_bp_id.GetLocationID());
8421b54c88cSJim Ingham                             const Baton *baton = bp_options->GetBaton();
84330fdc8d8SChris Lattner                             if (baton)
84430fdc8d8SChris Lattner                             {
84530fdc8d8SChris Lattner                                 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
84630fdc8d8SChris Lattner                                 result.GetOutputStream().IndentMore ();
84730fdc8d8SChris Lattner                                 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
84830fdc8d8SChris Lattner                                 result.GetOutputStream().IndentLess ();
84930fdc8d8SChris Lattner                             }
85030fdc8d8SChris Lattner                             else
85130fdc8d8SChris Lattner                             {
852e16c50a1SJim Ingham                                 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
853e16c50a1SJim Ingham                                                                 id_str.GetData());
85430fdc8d8SChris Lattner                             }
85530fdc8d8SChris Lattner                         }
85630fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishResult);
85730fdc8d8SChris Lattner                     }
85830fdc8d8SChris Lattner                     else
85930fdc8d8SChris Lattner                     {
86030fdc8d8SChris Lattner                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
86130fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusFailed);
86230fdc8d8SChris Lattner                     }
86330fdc8d8SChris Lattner 
86430fdc8d8SChris Lattner                 }
86530fdc8d8SChris Lattner             }
86630fdc8d8SChris Lattner         }
86730fdc8d8SChris Lattner 
86830fdc8d8SChris Lattner         return result.Succeeded();
86930fdc8d8SChris Lattner     }
8705a988416SJim Ingham };
87130fdc8d8SChris Lattner 
87230fdc8d8SChris Lattner //-------------------------------------------------------------------------
87330fdc8d8SChris Lattner // CommandObjectBreakpointCommand
87430fdc8d8SChris Lattner //-------------------------------------------------------------------------
87530fdc8d8SChris Lattner 
8766611103cSGreg Clayton CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
877a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
878a7015092SGreg Clayton                             "command",
8797050e0b1SSean Callanan                             "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
88030fdc8d8SChris Lattner                             "command <sub-command> [<sub-command-options>] <breakpoint-id>")
88130fdc8d8SChris Lattner {
882a7015092SGreg Clayton     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
88393e0f19fSCaroline Tice     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
884a7015092SGreg Clayton     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
88530fdc8d8SChris Lattner 
88630fdc8d8SChris Lattner     add_command_object->SetCommandName ("breakpoint command add");
88793e0f19fSCaroline Tice     delete_command_object->SetCommandName ("breakpoint command delete");
88830fdc8d8SChris Lattner     list_command_object->SetCommandName ("breakpoint command list");
88930fdc8d8SChris Lattner 
89023f59509SGreg Clayton     LoadSubCommand ("add",    add_command_object);
89123f59509SGreg Clayton     LoadSubCommand ("delete", delete_command_object);
89223f59509SGreg Clayton     LoadSubCommand ("list",   list_command_object);
89330fdc8d8SChris Lattner }
89430fdc8d8SChris Lattner 
89530fdc8d8SChris Lattner CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
89630fdc8d8SChris Lattner {
89730fdc8d8SChris Lattner }
89830fdc8d8SChris Lattner 
89930fdc8d8SChris Lattner 
900