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 (
52ea671fbdSKate Stone R"(
53ea671fbdSKate Stone General information about entering breakpoint commands
54ea671fbdSKate Stone ------------------------------------------------------
55ea671fbdSKate Stone 
56ea671fbdSKate Stone )" "This command will prompt for commands to be executed when the specified \
57ea671fbdSKate Stone breakpoint is hit.  Each command is typed on its own line following the '> ' \
58ea671fbdSKate Stone prompt until 'DONE' is entered." R"(
59ea671fbdSKate Stone 
60ea671fbdSKate Stone )" "Syntactic errors may not be detected when initially entered, and many \
61ea671fbdSKate Stone malformed commands can silently fail when executed.  If your breakpoint commands \
62ea671fbdSKate Stone do not appear to be executing, double-check the command syntax." R"(
63ea671fbdSKate Stone 
64ea671fbdSKate Stone )" "Note: You may enter any debugger command exactly as you would at the debugger \
65ea671fbdSKate Stone prompt.  There is no limit to the number of commands supplied, but do NOT enter \
66ea671fbdSKate Stone more than one command per line." R"(
67ea671fbdSKate Stone 
68ea671fbdSKate Stone Special information about PYTHON breakpoint commands
69ea671fbdSKate Stone ----------------------------------------------------
70ea671fbdSKate Stone 
71ea671fbdSKate Stone )" "You may enter either one or more lines of Python, including function \
72ea671fbdSKate Stone definitions or calls to functions that will have been imported by the time \
73ea671fbdSKate Stone the code executes.  Single line breakpoint commands will be interpreted 'as is' \
74ea671fbdSKate Stone when the breakpoint is hit.  Multiple lines of Python will be wrapped in a \
75ea671fbdSKate Stone generated function, and a call to the function will be attached to the breakpoint." R"(
76ea671fbdSKate Stone 
77ea671fbdSKate Stone This auto-generated function is passed in three arguments:
78ea671fbdSKate Stone 
79ea671fbdSKate Stone     frame:  an lldb.SBFrame object for the frame which hit breakpoint.
80ea671fbdSKate Stone 
81ea671fbdSKate Stone     bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
82ea671fbdSKate Stone 
83ea671fbdSKate Stone     dict:   the python session dictionary hit.
84ea671fbdSKate Stone 
85ea671fbdSKate Stone )" "When specifying a python function with the --python-function option, you need \
86ea671fbdSKate Stone to supply the function name prepended by the module name:" R"(
87ea671fbdSKate Stone 
88ea671fbdSKate Stone     --python-function myutils.breakpoint_callback
89ea671fbdSKate Stone 
90ea671fbdSKate Stone The function itself must have the following prototype:
91ea671fbdSKate Stone 
92ea671fbdSKate Stone def breakpoint_callback(frame, bp_loc, dict):
93ea671fbdSKate Stone   # Your code goes here
94ea671fbdSKate Stone 
95ea671fbdSKate Stone )" "The arguments are the same as the arguments passed to generated functions as \
96ea671fbdSKate Stone described above.  Note that the global variable 'lldb.frame' will NOT be updated when \
97ea671fbdSKate Stone this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
98ea671fbdSKate Stone can get you to the thread via frame.GetThread(), the thread can get you to the \
99ea671fbdSKate Stone process via thread.GetProcess(), and the process can get you back to the target \
100ea671fbdSKate Stone via process.GetTarget()." R"(
101ea671fbdSKate Stone 
102ea671fbdSKate Stone )" "Important Note: As Python code gets collected into functions, access to global \
103ea671fbdSKate Stone variables requires explicit scoping using the 'global' keyword.  Be sure to use correct \
104ea671fbdSKate Stone Python syntax, including indentation, when entering Python breakpoint commands." R"(
105ea671fbdSKate Stone 
106ea671fbdSKate Stone Example Python one-line breakpoint command:
107ea671fbdSKate Stone 
108ea671fbdSKate Stone (lldb) breakpoint command add -s python 1
109ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
110ea671fbdSKate Stone > print "Hit this breakpoint!"
111ea671fbdSKate Stone > DONE
112ea671fbdSKate Stone 
113ea671fbdSKate Stone As a convenience, this also works for a short Python one-liner:
114ea671fbdSKate Stone 
115ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
116ea671fbdSKate Stone (lldb) run
117ea671fbdSKate Stone Launching '.../a.out'  (x86_64)
118ea671fbdSKate Stone (lldb) Fri Sep 10 12:17:45 2010
119ea671fbdSKate Stone Process 21778 Stopped
120ea671fbdSKate Stone * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
121ea671fbdSKate Stone   36
122ea671fbdSKate Stone   37   	int c(int val)
123ea671fbdSKate Stone   38   	{
124ea671fbdSKate Stone   39 ->	    return val + 3;
125ea671fbdSKate Stone   40   	}
126ea671fbdSKate Stone   41
127ea671fbdSKate Stone   42   	int main (int argc, char const *argv[])
128ea671fbdSKate Stone 
129ea671fbdSKate Stone Example multiple line Python breakpoint command:
130ea671fbdSKate Stone 
131ea671fbdSKate Stone (lldb) breakpoint command add -s p 1
132ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
133ea671fbdSKate Stone > global bp_count
134ea671fbdSKate Stone > bp_count = bp_count + 1
135ea671fbdSKate Stone > print "Hit this breakpoint " + repr(bp_count) + " times!"
136ea671fbdSKate Stone > DONE
137ea671fbdSKate Stone 
138ea671fbdSKate Stone Example multiple line Python breakpoint command, using function definition:
139ea671fbdSKate Stone 
140ea671fbdSKate Stone (lldb) breakpoint command add -s python 1
141ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
142ea671fbdSKate Stone > def breakpoint_output (bp_no):
143ea671fbdSKate Stone >     out_string = "Hit breakpoint number " + repr (bp_no)
144ea671fbdSKate Stone >     print out_string
145ea671fbdSKate Stone >     return True
146ea671fbdSKate Stone > breakpoint_output (1)
147ea671fbdSKate Stone > DONE
148ea671fbdSKate Stone 
149ea671fbdSKate Stone )" "In this case, since there is a reference to a global variable, \
150ea671fbdSKate Stone 'bp_count', you will also need to make sure 'bp_count' exists and is \
151ea671fbdSKate Stone initialized:" R"(
152ea671fbdSKate Stone 
153ea671fbdSKate Stone (lldb) script
154ea671fbdSKate Stone >>> bp_count = 0
155ea671fbdSKate Stone >>> quit()
156ea671fbdSKate Stone 
157ea671fbdSKate Stone )" "Your Python code, however organized, can optionally return a value.  \
158ea671fbdSKate Stone If the returned value is False, that tells LLDB not to stop at the breakpoint \
159ea671fbdSKate Stone to which the code is associated. Returning anything other than False, or even \
160ea671fbdSKate Stone returning None, or even omitting a return statement entirely, will cause \
161ea671fbdSKate Stone LLDB to stop." R"(
162ea671fbdSKate Stone 
163ea671fbdSKate Stone )" "Final Note: A warning that no breakpoint command was generated when there \
164ea671fbdSKate Stone are no syntax errors may indicate that a function was declared but never called."
165ea671fbdSKate 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 
181*13d21e9aSBruce Mitchener     ~CommandObjectBreakpointCommandAdd () override {}
1825a988416SJim Ingham 
183*13d21e9aSBruce Mitchener     Options *
184*13d21e9aSBruce Mitchener     GetOptions () override
1855a988416SJim Ingham     {
1865a988416SJim Ingham         return &m_options;
1875a988416SJim Ingham     }
1885a988416SJim Ingham 
189*13d21e9aSBruce Mitchener     void
190*13d21e9aSBruce Mitchener     IOHandlerActivated (IOHandler &io_handler) override
19144d93782SGreg Clayton     {
19244d93782SGreg Clayton         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
19344d93782SGreg Clayton         if (output_sp)
19444d93782SGreg Clayton         {
19544d93782SGreg Clayton             output_sp->PutCString(g_reader_instructions);
19644d93782SGreg Clayton             output_sp->Flush();
19744d93782SGreg Clayton         }
19844d93782SGreg Clayton     }
19944d93782SGreg Clayton 
20044d93782SGreg Clayton 
201*13d21e9aSBruce Mitchener     void
202*13d21e9aSBruce Mitchener     IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override
20344d93782SGreg Clayton     {
20444d93782SGreg Clayton         io_handler.SetIsDone(true);
20544d93782SGreg Clayton 
206b5796cb4SJim Ingham         std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
207b5796cb4SJim Ingham         for (BreakpointOptions *bp_options : *bp_options_vec)
20844d93782SGreg Clayton         {
209b5796cb4SJim Ingham             if (!bp_options)
210b5796cb4SJim Ingham                 continue;
211b5796cb4SJim Ingham 
21244d93782SGreg Clayton             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
21344d93782SGreg Clayton             if (data_ap.get())
21444d93782SGreg Clayton             {
21544d93782SGreg Clayton                 data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
21644d93782SGreg Clayton                 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
21744d93782SGreg Clayton                 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
21844d93782SGreg Clayton             }
21944d93782SGreg Clayton         }
22044d93782SGreg Clayton     }
22144d93782SGreg Clayton 
2225a988416SJim Ingham     void
223b5796cb4SJim Ingham     CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
2245a988416SJim Ingham                                              CommandReturnObject &result)
2255a988416SJim Ingham     {
22644d93782SGreg Clayton         m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
22744d93782SGreg Clayton                                                     *this,          // IOHandlerDelegate
22844d93782SGreg Clayton                                                     true,           // Run IOHandler in async mode
229b5796cb4SJim Ingham                                                     &bp_options_vec);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
2305a988416SJim Ingham     }
2315a988416SJim Ingham 
2325a988416SJim Ingham     /// Set a one-liner as the callback for the breakpoint.
2335a988416SJim Ingham     void
234b5796cb4SJim Ingham     SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
2355a988416SJim Ingham                                   const char *oneliner)
2365a988416SJim Ingham     {
237b5796cb4SJim Ingham         for (auto bp_options : bp_options_vec)
238b5796cb4SJim Ingham         {
2397b0992d9SGreg Clayton             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
2405a988416SJim Ingham 
2415a988416SJim Ingham             // It's necessary to set both user_source and script_source to the oneliner.
2425a988416SJim Ingham             // The former is used to generate callback description (as in breakpoint command list)
2435a988416SJim Ingham             // while the latter is used for Python to interpret during the actual callback.
2445a988416SJim Ingham             data_ap->user_source.AppendString (oneliner);
2455a988416SJim Ingham             data_ap->script_source.assign (oneliner);
2465a988416SJim Ingham             data_ap->stop_on_error = m_options.m_stop_on_error;
2475a988416SJim Ingham 
2485a988416SJim Ingham             BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
2495a988416SJim Ingham             bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
250b5796cb4SJim Ingham         }
2515a988416SJim Ingham         return;
2525a988416SJim Ingham     }
2535a988416SJim Ingham 
2545a988416SJim Ingham     static bool
2555a988416SJim Ingham     BreakpointOptionsCallbackFunction (void *baton,
2565a988416SJim Ingham                                        StoppointCallbackContext *context,
2575a988416SJim Ingham                                        lldb::user_id_t break_id,
2585a988416SJim Ingham                                        lldb::user_id_t break_loc_id)
2595a988416SJim Ingham     {
2605a988416SJim Ingham         bool ret_value = true;
2615a988416SJim Ingham         if (baton == NULL)
2625a988416SJim Ingham             return true;
2635a988416SJim Ingham 
2645a988416SJim Ingham 
2655a988416SJim Ingham         BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
2665a988416SJim Ingham         StringList &commands = data->user_source;
2675a988416SJim Ingham 
2685a988416SJim Ingham         if (commands.GetSize() > 0)
2695a988416SJim Ingham         {
2705a988416SJim Ingham             ExecutionContext exe_ctx (context->exe_ctx_ref);
2715a988416SJim Ingham             Target *target = exe_ctx.GetTargetPtr();
2725a988416SJim Ingham             if (target)
2735a988416SJim Ingham             {
2745a988416SJim Ingham                 CommandReturnObject result;
2755a988416SJim Ingham                 Debugger &debugger = target->GetDebugger();
2765a988416SJim Ingham                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
2775a988416SJim Ingham                 // if the debugger is set up that way.
2785a988416SJim Ingham 
2795a988416SJim Ingham                 StreamSP output_stream (debugger.GetAsyncOutputStream());
2805a988416SJim Ingham                 StreamSP error_stream (debugger.GetAsyncErrorStream());
2815a988416SJim Ingham                 result.SetImmediateOutputStream (output_stream);
2825a988416SJim Ingham                 result.SetImmediateErrorStream (error_stream);
2835a988416SJim Ingham 
28426c7bf93SJim Ingham                 CommandInterpreterRunOptions options;
28526c7bf93SJim Ingham                 options.SetStopOnContinue(true);
28626c7bf93SJim Ingham                 options.SetStopOnError (data->stop_on_error);
28726c7bf93SJim Ingham                 options.SetEchoCommands (true);
28826c7bf93SJim Ingham                 options.SetPrintResults (true);
28926c7bf93SJim Ingham                 options.SetAddToHistory (false);
2905a988416SJim Ingham 
2915a988416SJim Ingham                 debugger.GetCommandInterpreter().HandleCommands (commands,
2925a988416SJim Ingham                                                                  &exe_ctx,
29326c7bf93SJim Ingham                                                                  options,
2945a988416SJim Ingham                                                                  result);
2955a988416SJim Ingham                 result.GetImmediateOutputStream()->Flush();
2965a988416SJim Ingham                 result.GetImmediateErrorStream()->Flush();
2975a988416SJim Ingham            }
2985a988416SJim Ingham         }
2995a988416SJim Ingham         return ret_value;
3005a988416SJim Ingham     }
3015a988416SJim Ingham 
3025a988416SJim Ingham     class CommandOptions : public Options
3035a988416SJim Ingham     {
3045a988416SJim Ingham     public:
3055a988416SJim Ingham 
3065a988416SJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
3075a988416SJim Ingham             Options (interpreter),
3085a988416SJim Ingham             m_use_commands (false),
3095a988416SJim Ingham             m_use_script_language (false),
3105a988416SJim Ingham             m_script_language (eScriptLanguageNone),
3115a988416SJim Ingham             m_use_one_liner (false),
3125a988416SJim Ingham             m_one_liner(),
3135a988416SJim Ingham             m_function_name()
31430fdc8d8SChris Lattner         {
31530fdc8d8SChris Lattner         }
31630fdc8d8SChris Lattner 
317*13d21e9aSBruce Mitchener         ~CommandOptions () override {}
3185a988416SJim Ingham 
319*13d21e9aSBruce Mitchener         Error
320*13d21e9aSBruce Mitchener         SetOptionValue (uint32_t option_idx, const char *option_arg) override
3215a988416SJim Ingham         {
3225a988416SJim Ingham             Error error;
3233bcdfc0eSGreg Clayton             const int short_option = m_getopt_table[option_idx].val;
3245a988416SJim Ingham 
3255a988416SJim Ingham             switch (short_option)
3265a988416SJim Ingham             {
3275a988416SJim Ingham             case 'o':
3285a988416SJim Ingham                 m_use_one_liner = true;
3295a988416SJim Ingham                 m_one_liner = option_arg;
3305a988416SJim Ingham                 break;
3315a988416SJim Ingham 
3325a988416SJim Ingham             case 's':
3335a988416SJim Ingham                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
3345a988416SJim Ingham                                                                                      g_option_table[option_idx].enum_values,
3355a988416SJim Ingham                                                                                      eScriptLanguageNone,
3365a988416SJim Ingham                                                                                      error);
3375a988416SJim Ingham 
3385a988416SJim Ingham                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
3395a988416SJim Ingham                 {
3405a988416SJim Ingham                     m_use_script_language = true;
3415a988416SJim Ingham                 }
3425a988416SJim Ingham                 else
3435a988416SJim Ingham                 {
3445a988416SJim Ingham                     m_use_script_language = false;
3455a988416SJim Ingham                 }
3465a988416SJim Ingham                 break;
3475a988416SJim Ingham 
3485a988416SJim Ingham             case 'e':
3495a988416SJim Ingham                 {
3505a988416SJim Ingham                     bool success = false;
3515a988416SJim Ingham                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
3525a988416SJim Ingham                     if (!success)
3535a988416SJim Ingham                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
3545a988416SJim Ingham                 }
3555a988416SJim Ingham                 break;
3565a988416SJim Ingham 
3575a988416SJim Ingham             case 'F':
3585a988416SJim Ingham                 {
3595a988416SJim Ingham                     m_use_one_liner = false;
3605a988416SJim Ingham                     m_use_script_language = true;
3615a988416SJim Ingham                     m_function_name.assign(option_arg);
3625a988416SJim Ingham                 }
3635a988416SJim Ingham                 break;
3645a988416SJim Ingham 
36533df7cd3SJim Ingham             case 'D':
36633df7cd3SJim Ingham                 m_use_dummy = true;
36733df7cd3SJim Ingham                 break;
36833df7cd3SJim Ingham 
3695a988416SJim Ingham             default:
3705a988416SJim Ingham                 break;
3715a988416SJim Ingham             }
3725a988416SJim Ingham             return error;
3735a988416SJim Ingham         }
3745a988416SJim Ingham         void
375*13d21e9aSBruce Mitchener         OptionParsingStarting () override
3765a988416SJim Ingham         {
3775a988416SJim Ingham             m_use_commands = true;
3785a988416SJim Ingham             m_use_script_language = false;
3795a988416SJim Ingham             m_script_language = eScriptLanguageNone;
3805a988416SJim Ingham 
3815a988416SJim Ingham             m_use_one_liner = false;
3825a988416SJim Ingham             m_stop_on_error = true;
3835a988416SJim Ingham             m_one_liner.clear();
3845a988416SJim Ingham             m_function_name.clear();
38533df7cd3SJim Ingham             m_use_dummy = false;
3865a988416SJim Ingham         }
3875a988416SJim Ingham 
3885a988416SJim Ingham         const OptionDefinition*
389*13d21e9aSBruce Mitchener         GetDefinitions () override
3905a988416SJim Ingham         {
3915a988416SJim Ingham             return g_option_table;
3925a988416SJim Ingham         }
3935a988416SJim Ingham 
3945a988416SJim Ingham         // Options table: Required for subclasses of Options.
3955a988416SJim Ingham 
3965a988416SJim Ingham         static OptionDefinition g_option_table[];
3975a988416SJim Ingham 
3985a988416SJim Ingham         // Instance variables to hold the values for command options.
3995a988416SJim Ingham 
4005a988416SJim Ingham         bool m_use_commands;
4015a988416SJim Ingham         bool m_use_script_language;
4025a988416SJim Ingham         lldb::ScriptLanguage m_script_language;
4035a988416SJim Ingham 
4045a988416SJim Ingham         // Instance variables to hold the values for one_liner options.
4055a988416SJim Ingham         bool m_use_one_liner;
4065a988416SJim Ingham         std::string m_one_liner;
4075a988416SJim Ingham         bool m_stop_on_error;
4085a988416SJim Ingham         std::string m_function_name;
40933df7cd3SJim Ingham         bool m_use_dummy;
4105a988416SJim Ingham     };
4115a988416SJim Ingham 
4125a988416SJim Ingham protected:
413*13d21e9aSBruce Mitchener     bool
414*13d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
41530fdc8d8SChris Lattner     {
41633df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
41730fdc8d8SChris Lattner 
41830fdc8d8SChris Lattner         if (target == NULL)
41930fdc8d8SChris Lattner         {
42030fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
42130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
42230fdc8d8SChris Lattner             return false;
42330fdc8d8SChris Lattner         }
42430fdc8d8SChris Lattner 
42530fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
42630fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
42730fdc8d8SChris Lattner 
42830fdc8d8SChris Lattner         if (num_breakpoints == 0)
42930fdc8d8SChris Lattner         {
43030fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist to have commands added");
43130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
43230fdc8d8SChris Lattner             return false;
43330fdc8d8SChris Lattner         }
43430fdc8d8SChris Lattner 
4358d4a8010SEnrico Granata         if (m_options.m_use_script_language == false && m_options.m_function_name.size())
4368d4a8010SEnrico Granata         {
4378d4a8010SEnrico Granata             result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
4388d4a8010SEnrico Granata             result.SetStatus (eReturnStatusFailed);
4398d4a8010SEnrico Granata             return false;
4408d4a8010SEnrico Granata         }
4418d4a8010SEnrico Granata 
44230fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
4435e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
44430fdc8d8SChris Lattner 
445b5796cb4SJim Ingham         m_bp_options_vec.clear();
446b5796cb4SJim Ingham 
44730fdc8d8SChris Lattner         if (result.Succeeded())
44830fdc8d8SChris Lattner         {
449c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
450d9916eaeSJim Ingham 
451c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
45230fdc8d8SChris Lattner             {
45330fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
45430fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
45530fdc8d8SChris Lattner                 {
45630fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
45739d7d4f0SJohnny Chen                     BreakpointOptions *bp_options = NULL;
45839d7d4f0SJohnny Chen                     if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
45939d7d4f0SJohnny Chen                     {
46039d7d4f0SJohnny Chen                         // This breakpoint does not have an associated location.
46139d7d4f0SJohnny Chen                         bp_options = bp->GetOptions();
46239d7d4f0SJohnny Chen                     }
46339d7d4f0SJohnny Chen                     else
46430fdc8d8SChris Lattner                     {
46530fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
46639d7d4f0SJohnny Chen                         // This breakpoint does have an associated location.
46739d7d4f0SJohnny Chen                         // Get its breakpoint options.
46830fdc8d8SChris Lattner                         if (bp_loc_sp)
46939d7d4f0SJohnny Chen                             bp_options = bp_loc_sp->GetLocationOptions();
47039d7d4f0SJohnny Chen                     }
471b5796cb4SJim Ingham                     if (bp_options)
472b5796cb4SJim Ingham                         m_bp_options_vec.push_back (bp_options);
473b5796cb4SJim Ingham                 }
474b5796cb4SJim Ingham             }
47539d7d4f0SJohnny Chen 
47639d7d4f0SJohnny Chen             // If we are using script language, get the script interpreter
47739d7d4f0SJohnny Chen             // in order to set or collect command callback.  Otherwise, call
47839d7d4f0SJohnny Chen             // the methods associated with this object.
47930fdc8d8SChris Lattner             if (m_options.m_use_script_language)
48030fdc8d8SChris Lattner             {
481b5796cb4SJim Ingham                 ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
48239d7d4f0SJohnny Chen                 // Special handling for one-liner specified inline.
48339d7d4f0SJohnny Chen                 if (m_options.m_use_one_liner)
4848d4a8010SEnrico Granata                 {
485b5796cb4SJim Ingham                     script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
48639d7d4f0SJohnny Chen                                                                  m_options.m_one_liner.c_str());
4878d4a8010SEnrico Granata                 }
4888d4a8010SEnrico Granata                 else if (m_options.m_function_name.size())
4898d4a8010SEnrico Granata                 {
490b5796cb4SJim Ingham                     script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
491d80102e4SJim Ingham                                                                          m_options.m_function_name.c_str());
4928d4a8010SEnrico Granata                 }
49394de55d5SJohnny Chen                 else
4948d4a8010SEnrico Granata                 {
495b5796cb4SJim Ingham                     script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
49630fdc8d8SChris Lattner                                                                             result);
49730fdc8d8SChris Lattner                 }
4988d4a8010SEnrico Granata             }
49930fdc8d8SChris Lattner             else
50030fdc8d8SChris Lattner             {
50139d7d4f0SJohnny Chen                 // Special handling for one-liner specified inline.
50239d7d4f0SJohnny Chen                 if (m_options.m_use_one_liner)
503b5796cb4SJim Ingham                     SetBreakpointCommandCallback (m_bp_options_vec,
50439d7d4f0SJohnny Chen                                                   m_options.m_one_liner.c_str());
50539d7d4f0SJohnny Chen                 else
506b5796cb4SJim Ingham                     CollectDataForBreakpointCommandCallback (m_bp_options_vec,
507b132097bSGreg Clayton                                                              result);
50830fdc8d8SChris Lattner             }
509b5796cb4SJim Ingham 
51030fdc8d8SChris Lattner         }
51130fdc8d8SChris Lattner 
51230fdc8d8SChris Lattner         return result.Succeeded();
51330fdc8d8SChris Lattner     }
51430fdc8d8SChris Lattner 
5155a988416SJim Ingham private:
5165a988416SJim Ingham     CommandOptions m_options;
517b5796cb4SJim Ingham     std::vector<BreakpointOptions *> m_bp_options_vec;  // This stores the breakpoint options that we are currently
518b5796cb4SJim Ingham                                                         // collecting commands for.  In the CollectData... calls we need
519b5796cb4SJim Ingham                                                         // to hand this off to the IOHandler, which may run asynchronously.
520b5796cb4SJim Ingham                                                         // So we have to have some way to keep it alive, and not leak it.
521b5796cb4SJim Ingham                                                         // Making it an ivar of the command object, which never goes away
522b5796cb4SJim Ingham                                                         // achieves this.  Note that if we were able to run
523b5796cb4SJim Ingham                                                         // the same command concurrently in one interpreter we'd have to
524b5796cb4SJim Ingham                                                         // make this "per invocation".  But there are many more reasons
525b5796cb4SJim Ingham                                                         // why it is not in general safe to do that in lldb at present,
526b5796cb4SJim Ingham                                                         // so it isn't worthwhile to come up with a more complex mechanism
527b5796cb4SJim Ingham                                                         // to address this particular weakness right now.
5285a988416SJim Ingham     static const char *g_reader_instructions;
5295a988416SJim Ingham 
5305a988416SJim Ingham };
5315a988416SJim Ingham 
5325a988416SJim Ingham const char *
53344d93782SGreg Clayton CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.\n";
5345a988416SJim Ingham 
5355a988416SJim Ingham // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
5365a988416SJim Ingham // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
5375a988416SJim Ingham 
5385a988416SJim Ingham static OptionEnumValueElement
5395a988416SJim Ingham g_script_option_enumeration[4] =
54030fdc8d8SChris Lattner {
5415a988416SJim Ingham     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
5425a988416SJim Ingham     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
5435a988416SJim Ingham     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
5445a988416SJim Ingham     { 0,                      NULL,              NULL }
5455a988416SJim Ingham };
54630fdc8d8SChris Lattner 
5475a988416SJim Ingham OptionDefinition
5485a988416SJim Ingham CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
54930fdc8d8SChris Lattner {
550d37221dcSZachary Turner     { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
5515a988416SJim Ingham         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
55230fdc8d8SChris Lattner 
553d37221dcSZachary Turner     { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
5545a988416SJim Ingham         "Specify whether breakpoint command execution should terminate on error." },
55530fdc8d8SChris Lattner 
556d37221dcSZachary Turner     { LLDB_OPT_SET_ALL,   false, "script-type",     's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
5575a988416SJim Ingham         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
55830fdc8d8SChris Lattner 
559d37221dcSZachary Turner     { LLDB_OPT_SET_2,   false, "python-function",     'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
5605a988416SJim Ingham         "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
56139d7d4f0SJohnny Chen 
56233df7cd3SJim Ingham     { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
56333df7cd3SJim Ingham         "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
56433df7cd3SJim Ingham 
565d37221dcSZachary Turner     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
5665a988416SJim Ingham };
56730fdc8d8SChris Lattner 
56830fdc8d8SChris Lattner //-------------------------------------------------------------------------
56993e0f19fSCaroline Tice // CommandObjectBreakpointCommandDelete
57030fdc8d8SChris Lattner //-------------------------------------------------------------------------
57130fdc8d8SChris Lattner 
5725a988416SJim Ingham class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
5735a988416SJim Ingham {
5745a988416SJim Ingham public:
5755a988416SJim Ingham     CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
5765a988416SJim Ingham         CommandObjectParsed (interpreter,
57793e0f19fSCaroline Tice                              "delete",
57893e0f19fSCaroline Tice                              "Delete the set of commands from a breakpoint.",
57933df7cd3SJim Ingham                              NULL),
58033df7cd3SJim Ingham         m_options (interpreter)
58130fdc8d8SChris Lattner     {
582405fe67fSCaroline Tice         CommandArgumentEntry arg;
583405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
584405fe67fSCaroline Tice 
585405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
586405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
587405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
588405fe67fSCaroline Tice 
589405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
590405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
591405fe67fSCaroline Tice 
592405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
593405fe67fSCaroline Tice         m_arguments.push_back (arg);
59430fdc8d8SChris Lattner     }
59530fdc8d8SChris Lattner 
59630fdc8d8SChris Lattner 
597*13d21e9aSBruce Mitchener     ~CommandObjectBreakpointCommandDelete () override {}
5985a988416SJim Ingham 
599*13d21e9aSBruce Mitchener     Options *
600*13d21e9aSBruce Mitchener     GetOptions () override
60133df7cd3SJim Ingham     {
60233df7cd3SJim Ingham         return &m_options;
60333df7cd3SJim Ingham     }
60433df7cd3SJim Ingham 
60533df7cd3SJim Ingham     class CommandOptions : public Options
60633df7cd3SJim Ingham     {
60733df7cd3SJim Ingham     public:
60833df7cd3SJim Ingham 
60933df7cd3SJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
61033df7cd3SJim Ingham             Options (interpreter),
61133df7cd3SJim Ingham             m_use_dummy (false)
61233df7cd3SJim Ingham         {
61333df7cd3SJim Ingham         }
61433df7cd3SJim Ingham 
615*13d21e9aSBruce Mitchener         ~CommandOptions () override {}
61633df7cd3SJim Ingham 
617*13d21e9aSBruce Mitchener         Error
618*13d21e9aSBruce Mitchener         SetOptionValue (uint32_t option_idx, const char *option_arg) override
61933df7cd3SJim Ingham         {
62033df7cd3SJim Ingham             Error error;
62133df7cd3SJim Ingham             const int short_option = m_getopt_table[option_idx].val;
62233df7cd3SJim Ingham 
62333df7cd3SJim Ingham             switch (short_option)
62433df7cd3SJim Ingham             {
62533df7cd3SJim Ingham                 case 'D':
62633df7cd3SJim Ingham                     m_use_dummy = true;
62733df7cd3SJim Ingham                     break;
62833df7cd3SJim Ingham 
62933df7cd3SJim Ingham                 default:
63033df7cd3SJim Ingham                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
63133df7cd3SJim Ingham                     break;
63233df7cd3SJim Ingham             }
63333df7cd3SJim Ingham 
63433df7cd3SJim Ingham             return error;
63533df7cd3SJim Ingham         }
63633df7cd3SJim Ingham 
63733df7cd3SJim Ingham         void
638*13d21e9aSBruce Mitchener         OptionParsingStarting () override
63933df7cd3SJim Ingham         {
64033df7cd3SJim Ingham             m_use_dummy = false;
64133df7cd3SJim Ingham         }
64233df7cd3SJim Ingham 
64333df7cd3SJim Ingham         const OptionDefinition*
644*13d21e9aSBruce Mitchener         GetDefinitions () override
64533df7cd3SJim Ingham         {
64633df7cd3SJim Ingham             return g_option_table;
64733df7cd3SJim Ingham         }
64833df7cd3SJim Ingham 
64933df7cd3SJim Ingham         // Options table: Required for subclasses of Options.
65033df7cd3SJim Ingham 
65133df7cd3SJim Ingham         static OptionDefinition g_option_table[];
65233df7cd3SJim Ingham 
65333df7cd3SJim Ingham         // Instance variables to hold the values for command options.
65433df7cd3SJim Ingham         bool m_use_dummy;
65533df7cd3SJim Ingham     };
65633df7cd3SJim Ingham 
6575a988416SJim Ingham protected:
658*13d21e9aSBruce Mitchener     bool
659*13d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
66030fdc8d8SChris Lattner     {
66133df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
66230fdc8d8SChris Lattner 
66330fdc8d8SChris Lattner         if (target == NULL)
66430fdc8d8SChris Lattner         {
66593e0f19fSCaroline Tice             result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
66630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
66730fdc8d8SChris Lattner             return false;
66830fdc8d8SChris Lattner         }
66930fdc8d8SChris Lattner 
67030fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
67130fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
67230fdc8d8SChris Lattner 
67330fdc8d8SChris Lattner         if (num_breakpoints == 0)
67430fdc8d8SChris Lattner         {
67593e0f19fSCaroline Tice             result.AppendError ("No breakpoints exist to have commands deleted");
67630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
67730fdc8d8SChris Lattner             return false;
67830fdc8d8SChris Lattner         }
67930fdc8d8SChris Lattner 
68030fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
68130fdc8d8SChris Lattner         {
68293e0f19fSCaroline Tice             result.AppendError ("No breakpoint specified from which to delete the commands");
68330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
68430fdc8d8SChris Lattner             return false;
68530fdc8d8SChris Lattner         }
68630fdc8d8SChris Lattner 
68730fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
6885e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
68930fdc8d8SChris Lattner 
69030fdc8d8SChris Lattner         if (result.Succeeded())
69130fdc8d8SChris Lattner         {
692c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
693c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
69430fdc8d8SChris Lattner             {
69530fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
69630fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
69730fdc8d8SChris Lattner                 {
69830fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
69930fdc8d8SChris Lattner                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
70030fdc8d8SChris Lattner                     {
70130fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
70230fdc8d8SChris Lattner                         if (bp_loc_sp)
70330fdc8d8SChris Lattner                             bp_loc_sp->ClearCallback();
70430fdc8d8SChris Lattner                         else
70530fdc8d8SChris Lattner                         {
70630fdc8d8SChris Lattner                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
70730fdc8d8SChris Lattner                                                          cur_bp_id.GetBreakpointID(),
70830fdc8d8SChris Lattner                                                          cur_bp_id.GetLocationID());
70930fdc8d8SChris Lattner                             result.SetStatus (eReturnStatusFailed);
71030fdc8d8SChris Lattner                             return false;
71130fdc8d8SChris Lattner                         }
71230fdc8d8SChris Lattner                     }
71330fdc8d8SChris Lattner                     else
71430fdc8d8SChris Lattner                     {
71530fdc8d8SChris Lattner                         bp->ClearCallback();
71630fdc8d8SChris Lattner                     }
71730fdc8d8SChris Lattner                 }
71830fdc8d8SChris Lattner             }
71930fdc8d8SChris Lattner         }
72030fdc8d8SChris Lattner         return result.Succeeded();
72130fdc8d8SChris Lattner     }
72233df7cd3SJim Ingham private:
72333df7cd3SJim Ingham     CommandOptions m_options;
7245a988416SJim Ingham };
72530fdc8d8SChris Lattner 
72633df7cd3SJim Ingham OptionDefinition
72733df7cd3SJim Ingham CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
72833df7cd3SJim Ingham {
72933df7cd3SJim Ingham     { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
73033df7cd3SJim Ingham         "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
73133df7cd3SJim Ingham 
73233df7cd3SJim Ingham     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
73333df7cd3SJim Ingham };
73433df7cd3SJim Ingham 
73533df7cd3SJim Ingham 
73630fdc8d8SChris Lattner //-------------------------------------------------------------------------
73730fdc8d8SChris Lattner // CommandObjectBreakpointCommandList
73830fdc8d8SChris Lattner //-------------------------------------------------------------------------
73930fdc8d8SChris Lattner 
7405a988416SJim Ingham class CommandObjectBreakpointCommandList : public CommandObjectParsed
7415a988416SJim Ingham {
7425a988416SJim Ingham public:
7435a988416SJim Ingham     CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
7445a988416SJim Ingham         CommandObjectParsed (interpreter,
745a7015092SGreg Clayton                              "list",
74630fdc8d8SChris Lattner                              "List the script or set of commands to be executed when the breakpoint is hit.",
747405fe67fSCaroline Tice                               NULL)
74830fdc8d8SChris Lattner     {
749405fe67fSCaroline Tice         CommandArgumentEntry arg;
750405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
751405fe67fSCaroline Tice 
752405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
753405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
754405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
755405fe67fSCaroline Tice 
756405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
757405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
758405fe67fSCaroline Tice 
759405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
760405fe67fSCaroline Tice         m_arguments.push_back (arg);
76130fdc8d8SChris Lattner     }
76230fdc8d8SChris Lattner 
763*13d21e9aSBruce Mitchener     ~CommandObjectBreakpointCommandList () override {}
76430fdc8d8SChris Lattner 
7655a988416SJim Ingham protected:
766*13d21e9aSBruce Mitchener     bool
7675a988416SJim Ingham     DoExecute (Args& command,
768*13d21e9aSBruce Mitchener              CommandReturnObject &result) override
76930fdc8d8SChris Lattner     {
770a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
77130fdc8d8SChris Lattner 
77230fdc8d8SChris Lattner         if (target == NULL)
77330fdc8d8SChris Lattner         {
77430fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
77530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
77630fdc8d8SChris Lattner             return false;
77730fdc8d8SChris Lattner         }
77830fdc8d8SChris Lattner 
77930fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
78030fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
78130fdc8d8SChris Lattner 
78230fdc8d8SChris Lattner         if (num_breakpoints == 0)
78330fdc8d8SChris Lattner         {
78430fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist for which to list commands");
78530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
78630fdc8d8SChris Lattner             return false;
78730fdc8d8SChris Lattner         }
78830fdc8d8SChris Lattner 
78930fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
79030fdc8d8SChris Lattner         {
79130fdc8d8SChris Lattner             result.AppendError ("No breakpoint specified for which to list the commands");
79230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
79330fdc8d8SChris Lattner             return false;
79430fdc8d8SChris Lattner         }
79530fdc8d8SChris Lattner 
79630fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
7975e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
79830fdc8d8SChris Lattner 
79930fdc8d8SChris Lattner         if (result.Succeeded())
80030fdc8d8SChris Lattner         {
801c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
802c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
80330fdc8d8SChris Lattner             {
80430fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
80530fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
80630fdc8d8SChris Lattner                 {
80730fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
80830fdc8d8SChris Lattner 
80930fdc8d8SChris Lattner                     if (bp)
81030fdc8d8SChris Lattner                     {
8111b54c88cSJim Ingham                         const BreakpointOptions *bp_options = NULL;
81230fdc8d8SChris Lattner                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
81330fdc8d8SChris Lattner                         {
81430fdc8d8SChris Lattner                             BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
81530fdc8d8SChris Lattner                             if (bp_loc_sp)
81605407f6bSJim Ingham                                 bp_options = bp_loc_sp->GetOptionsNoCreate();
81730fdc8d8SChris Lattner                             else
81830fdc8d8SChris Lattner                             {
81930fdc8d8SChris Lattner                                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
82030fdc8d8SChris Lattner                                                              cur_bp_id.GetBreakpointID(),
82130fdc8d8SChris Lattner                                                              cur_bp_id.GetLocationID());
82230fdc8d8SChris Lattner                                 result.SetStatus (eReturnStatusFailed);
82330fdc8d8SChris Lattner                                 return false;
82430fdc8d8SChris Lattner                             }
82530fdc8d8SChris Lattner                         }
82630fdc8d8SChris Lattner                         else
82730fdc8d8SChris Lattner                         {
82830fdc8d8SChris Lattner                             bp_options = bp->GetOptions();
82930fdc8d8SChris Lattner                         }
83030fdc8d8SChris Lattner 
83130fdc8d8SChris Lattner                         if (bp_options)
83230fdc8d8SChris Lattner                         {
83330fdc8d8SChris Lattner                             StreamString id_str;
834e16c50a1SJim Ingham                             BreakpointID::GetCanonicalReference (&id_str,
835e16c50a1SJim Ingham                                                                  cur_bp_id.GetBreakpointID(),
836e16c50a1SJim Ingham                                                                  cur_bp_id.GetLocationID());
8371b54c88cSJim Ingham                             const Baton *baton = bp_options->GetBaton();
83830fdc8d8SChris Lattner                             if (baton)
83930fdc8d8SChris Lattner                             {
84030fdc8d8SChris Lattner                                 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
84130fdc8d8SChris Lattner                                 result.GetOutputStream().IndentMore ();
84230fdc8d8SChris Lattner                                 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
84330fdc8d8SChris Lattner                                 result.GetOutputStream().IndentLess ();
84430fdc8d8SChris Lattner                             }
84530fdc8d8SChris Lattner                             else
84630fdc8d8SChris Lattner                             {
847e16c50a1SJim Ingham                                 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
848e16c50a1SJim Ingham                                                                 id_str.GetData());
84930fdc8d8SChris Lattner                             }
85030fdc8d8SChris Lattner                         }
85130fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishResult);
85230fdc8d8SChris Lattner                     }
85330fdc8d8SChris Lattner                     else
85430fdc8d8SChris Lattner                     {
85530fdc8d8SChris Lattner                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
85630fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusFailed);
85730fdc8d8SChris Lattner                     }
85830fdc8d8SChris Lattner 
85930fdc8d8SChris Lattner                 }
86030fdc8d8SChris Lattner             }
86130fdc8d8SChris Lattner         }
86230fdc8d8SChris Lattner 
86330fdc8d8SChris Lattner         return result.Succeeded();
86430fdc8d8SChris Lattner     }
8655a988416SJim Ingham };
86630fdc8d8SChris Lattner 
86730fdc8d8SChris Lattner //-------------------------------------------------------------------------
86830fdc8d8SChris Lattner // CommandObjectBreakpointCommand
86930fdc8d8SChris Lattner //-------------------------------------------------------------------------
87030fdc8d8SChris Lattner 
8716611103cSGreg Clayton CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
872a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
873a7015092SGreg Clayton                             "command",
8747050e0b1SSean Callanan                             "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
87530fdc8d8SChris Lattner                             "command <sub-command> [<sub-command-options>] <breakpoint-id>")
87630fdc8d8SChris Lattner {
877a7015092SGreg Clayton     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
87893e0f19fSCaroline Tice     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
879a7015092SGreg Clayton     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
88030fdc8d8SChris Lattner 
88130fdc8d8SChris Lattner     add_command_object->SetCommandName ("breakpoint command add");
88293e0f19fSCaroline Tice     delete_command_object->SetCommandName ("breakpoint command delete");
88330fdc8d8SChris Lattner     list_command_object->SetCommandName ("breakpoint command list");
88430fdc8d8SChris Lattner 
88523f59509SGreg Clayton     LoadSubCommand ("add",    add_command_object);
88623f59509SGreg Clayton     LoadSubCommand ("delete", delete_command_object);
88723f59509SGreg Clayton     LoadSubCommand ("list",   list_command_object);
88830fdc8d8SChris Lattner }
88930fdc8d8SChris Lattner 
89030fdc8d8SChris Lattner CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
89130fdc8d8SChris Lattner {
89230fdc8d8SChris Lattner }
89330fdc8d8SChris Lattner 
89430fdc8d8SChris Lattner 
895