1ac7ddfbfSEd Maste //===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste // C Includes
11ac7ddfbfSEd Maste // C++ Includes
12ac7ddfbfSEd Maste 
13ac7ddfbfSEd Maste 
14ac7ddfbfSEd Maste #include "CommandObjectBreakpointCommand.h"
15ac7ddfbfSEd Maste #include "CommandObjectBreakpoint.h"
16ac7ddfbfSEd Maste 
1712b93ac6SEd Maste #include "lldb/Core/IOHandler.h"
18ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
19ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
20ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
21ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
22ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointIDList.h"
23ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
24ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
25ac7ddfbfSEd Maste #include "lldb/Breakpoint/StoppointCallbackContext.h"
26ac7ddfbfSEd Maste #include "lldb/Core/State.h"
27ac7ddfbfSEd Maste 
28ac7ddfbfSEd Maste using namespace lldb;
29ac7ddfbfSEd Maste using namespace lldb_private;
30ac7ddfbfSEd Maste 
31ac7ddfbfSEd Maste //-------------------------------------------------------------------------
32ac7ddfbfSEd Maste // CommandObjectBreakpointCommandAdd
33ac7ddfbfSEd Maste //-------------------------------------------------------------------------
34ac7ddfbfSEd Maste 
35ac7ddfbfSEd Maste 
3612b93ac6SEd Maste class CommandObjectBreakpointCommandAdd :
3712b93ac6SEd Maste     public CommandObjectParsed,
3812b93ac6SEd Maste     public IOHandlerDelegateMultiline
39ac7ddfbfSEd Maste {
40ac7ddfbfSEd Maste public:
41ac7ddfbfSEd Maste 
42ac7ddfbfSEd Maste     CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
43ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
44ac7ddfbfSEd Maste                              "add",
450127ef0fSEd Maste                              "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit."
460127ef0fSEd Maste                              "  If no breakpoint is specified, adds the commands to the last created breakpoint.",
47ac7ddfbfSEd Maste                              NULL),
4812b93ac6SEd Maste         IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
49ac7ddfbfSEd Maste         m_options (interpreter)
50ac7ddfbfSEd Maste     {
51ac7ddfbfSEd Maste         SetHelpLong (
52b91a7dfcSDimitry Andric R"(
53b91a7dfcSDimitry Andric General information about entering breakpoint commands
54b91a7dfcSDimitry Andric ------------------------------------------------------
55b91a7dfcSDimitry Andric 
56b91a7dfcSDimitry Andric )" "This command will prompt for commands to be executed when the specified \
57b91a7dfcSDimitry Andric breakpoint is hit.  Each command is typed on its own line following the '> ' \
58b91a7dfcSDimitry Andric prompt until 'DONE' is entered." R"(
59b91a7dfcSDimitry Andric 
60b91a7dfcSDimitry Andric )" "Syntactic errors may not be detected when initially entered, and many \
61b91a7dfcSDimitry Andric malformed commands can silently fail when executed.  If your breakpoint commands \
62b91a7dfcSDimitry Andric do not appear to be executing, double-check the command syntax." R"(
63b91a7dfcSDimitry Andric 
64b91a7dfcSDimitry Andric )" "Note: You may enter any debugger command exactly as you would at the debugger \
65b91a7dfcSDimitry Andric prompt.  There is no limit to the number of commands supplied, but do NOT enter \
66b91a7dfcSDimitry Andric more than one command per line." R"(
67b91a7dfcSDimitry Andric 
68b91a7dfcSDimitry Andric Special information about PYTHON breakpoint commands
69b91a7dfcSDimitry Andric ----------------------------------------------------
70b91a7dfcSDimitry Andric 
71b91a7dfcSDimitry Andric )" "You may enter either one or more lines of Python, including function \
72b91a7dfcSDimitry Andric definitions or calls to functions that will have been imported by the time \
73b91a7dfcSDimitry Andric the code executes.  Single line breakpoint commands will be interpreted 'as is' \
74b91a7dfcSDimitry Andric when the breakpoint is hit.  Multiple lines of Python will be wrapped in a \
75b91a7dfcSDimitry Andric generated function, and a call to the function will be attached to the breakpoint." R"(
76b91a7dfcSDimitry Andric 
77b91a7dfcSDimitry Andric This auto-generated function is passed in three arguments:
78b91a7dfcSDimitry Andric 
79b91a7dfcSDimitry Andric     frame:  an lldb.SBFrame object for the frame which hit breakpoint.
80b91a7dfcSDimitry Andric 
81b91a7dfcSDimitry Andric     bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
82b91a7dfcSDimitry Andric 
83b91a7dfcSDimitry Andric     dict:   the python session dictionary hit.
84b91a7dfcSDimitry Andric 
85b91a7dfcSDimitry Andric )" "When specifying a python function with the --python-function option, you need \
86b91a7dfcSDimitry Andric to supply the function name prepended by the module name:" R"(
87b91a7dfcSDimitry Andric 
88b91a7dfcSDimitry Andric     --python-function myutils.breakpoint_callback
89b91a7dfcSDimitry Andric 
90b91a7dfcSDimitry Andric The function itself must have the following prototype:
91b91a7dfcSDimitry Andric 
92b91a7dfcSDimitry Andric def breakpoint_callback(frame, bp_loc, dict):
93b91a7dfcSDimitry Andric   # Your code goes here
94b91a7dfcSDimitry Andric 
95b91a7dfcSDimitry Andric )" "The arguments are the same as the arguments passed to generated functions as \
96b91a7dfcSDimitry Andric described above.  Note that the global variable 'lldb.frame' will NOT be updated when \
97b91a7dfcSDimitry Andric this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
98b91a7dfcSDimitry Andric can get you to the thread via frame.GetThread(), the thread can get you to the \
99b91a7dfcSDimitry Andric process via thread.GetProcess(), and the process can get you back to the target \
100b91a7dfcSDimitry Andric via process.GetTarget()." R"(
101b91a7dfcSDimitry Andric 
102b91a7dfcSDimitry Andric )" "Important Note: As Python code gets collected into functions, access to global \
103b91a7dfcSDimitry Andric variables requires explicit scoping using the 'global' keyword.  Be sure to use correct \
104b91a7dfcSDimitry Andric Python syntax, including indentation, when entering Python breakpoint commands." R"(
105b91a7dfcSDimitry Andric 
106b91a7dfcSDimitry Andric Example Python one-line breakpoint command:
107b91a7dfcSDimitry Andric 
108b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1
109b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
110b91a7dfcSDimitry Andric > print "Hit this breakpoint!"
111b91a7dfcSDimitry Andric > DONE
112b91a7dfcSDimitry Andric 
113b91a7dfcSDimitry Andric As a convenience, this also works for a short Python one-liner:
114b91a7dfcSDimitry Andric 
115b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
116b91a7dfcSDimitry Andric (lldb) run
117b91a7dfcSDimitry Andric Launching '.../a.out'  (x86_64)
118b91a7dfcSDimitry Andric (lldb) Fri Sep 10 12:17:45 2010
119b91a7dfcSDimitry Andric Process 21778 Stopped
120b91a7dfcSDimitry Andric * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
121b91a7dfcSDimitry Andric   36
122b91a7dfcSDimitry Andric   37   	int c(int val)
123b91a7dfcSDimitry Andric   38   	{
124b91a7dfcSDimitry Andric   39 ->	    return val + 3;
125b91a7dfcSDimitry Andric   40   	}
126b91a7dfcSDimitry Andric   41
127b91a7dfcSDimitry Andric   42   	int main (int argc, char const *argv[])
128b91a7dfcSDimitry Andric 
129b91a7dfcSDimitry Andric Example multiple line Python breakpoint command:
130b91a7dfcSDimitry Andric 
131b91a7dfcSDimitry Andric (lldb) breakpoint command add -s p 1
132b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
133b91a7dfcSDimitry Andric > global bp_count
134b91a7dfcSDimitry Andric > bp_count = bp_count + 1
135b91a7dfcSDimitry Andric > print "Hit this breakpoint " + repr(bp_count) + " times!"
136b91a7dfcSDimitry Andric > DONE
137b91a7dfcSDimitry Andric 
138b91a7dfcSDimitry Andric Example multiple line Python breakpoint command, using function definition:
139b91a7dfcSDimitry Andric 
140b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1
141b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
142b91a7dfcSDimitry Andric > def breakpoint_output (bp_no):
143b91a7dfcSDimitry Andric >     out_string = "Hit breakpoint number " + repr (bp_no)
144b91a7dfcSDimitry Andric >     print out_string
145b91a7dfcSDimitry Andric >     return True
146b91a7dfcSDimitry Andric > breakpoint_output (1)
147b91a7dfcSDimitry Andric > DONE
148b91a7dfcSDimitry Andric 
149b91a7dfcSDimitry Andric )" "In this case, since there is a reference to a global variable, \
150b91a7dfcSDimitry Andric 'bp_count', you will also need to make sure 'bp_count' exists and is \
151b91a7dfcSDimitry Andric initialized:" R"(
152b91a7dfcSDimitry Andric 
153b91a7dfcSDimitry Andric (lldb) script
154b91a7dfcSDimitry Andric >>> bp_count = 0
155b91a7dfcSDimitry Andric >>> quit()
156b91a7dfcSDimitry Andric 
157b91a7dfcSDimitry Andric )" "Your Python code, however organized, can optionally return a value.  \
158b91a7dfcSDimitry Andric If the returned value is False, that tells LLDB not to stop at the breakpoint \
159b91a7dfcSDimitry Andric to which the code is associated. Returning anything other than False, or even \
160b91a7dfcSDimitry Andric returning None, or even omitting a return statement entirely, will cause \
161b91a7dfcSDimitry Andric LLDB to stop." R"(
162b91a7dfcSDimitry Andric 
163b91a7dfcSDimitry Andric )" "Final Note: A warning that no breakpoint command was generated when there \
164b91a7dfcSDimitry Andric are no syntax errors may indicate that a function was declared but never called."
165b91a7dfcSDimitry Andric         );
166ac7ddfbfSEd Maste 
167ac7ddfbfSEd Maste         CommandArgumentEntry arg;
168ac7ddfbfSEd Maste         CommandArgumentData bp_id_arg;
169ac7ddfbfSEd Maste 
170ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
171ac7ddfbfSEd Maste         bp_id_arg.arg_type = eArgTypeBreakpointID;
1720127ef0fSEd Maste         bp_id_arg.arg_repetition = eArgRepeatOptional;
173ac7ddfbfSEd Maste 
174ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
175ac7ddfbfSEd Maste         arg.push_back (bp_id_arg);
176ac7ddfbfSEd Maste 
177ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
178ac7ddfbfSEd Maste         m_arguments.push_back (arg);
179ac7ddfbfSEd Maste     }
180ac7ddfbfSEd Maste 
1819f2f44ceSEd Maste     ~CommandObjectBreakpointCommandAdd () override {}
182ac7ddfbfSEd Maste 
1839f2f44ceSEd Maste     Options *
1849f2f44ceSEd Maste     GetOptions () override
185ac7ddfbfSEd Maste     {
186ac7ddfbfSEd Maste         return &m_options;
187ac7ddfbfSEd Maste     }
188ac7ddfbfSEd Maste 
1899f2f44ceSEd Maste     void
1909f2f44ceSEd Maste     IOHandlerActivated (IOHandler &io_handler) override
19112b93ac6SEd Maste     {
19212b93ac6SEd Maste         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
19312b93ac6SEd Maste         if (output_sp)
19412b93ac6SEd Maste         {
19512b93ac6SEd Maste             output_sp->PutCString(g_reader_instructions);
19612b93ac6SEd Maste             output_sp->Flush();
19712b93ac6SEd Maste         }
19812b93ac6SEd Maste     }
19912b93ac6SEd Maste 
20012b93ac6SEd Maste 
2019f2f44ceSEd Maste     void
2029f2f44ceSEd Maste     IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override
20312b93ac6SEd Maste     {
20412b93ac6SEd Maste         io_handler.SetIsDone(true);
20512b93ac6SEd Maste 
2060127ef0fSEd Maste         std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
2070127ef0fSEd Maste         for (BreakpointOptions *bp_options : *bp_options_vec)
20812b93ac6SEd Maste         {
2090127ef0fSEd Maste             if (!bp_options)
2100127ef0fSEd Maste                 continue;
2110127ef0fSEd Maste 
21212b93ac6SEd Maste             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
21312b93ac6SEd Maste             if (data_ap.get())
21412b93ac6SEd Maste             {
21512b93ac6SEd Maste                 data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
21612b93ac6SEd Maste                 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
21712b93ac6SEd Maste                 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
21812b93ac6SEd Maste             }
21912b93ac6SEd Maste         }
22012b93ac6SEd Maste     }
22112b93ac6SEd Maste 
222ac7ddfbfSEd Maste     void
2230127ef0fSEd Maste     CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
224ac7ddfbfSEd Maste                                              CommandReturnObject &result)
225ac7ddfbfSEd Maste     {
22612b93ac6SEd Maste         m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
22712b93ac6SEd Maste                                                     *this,          // IOHandlerDelegate
22812b93ac6SEd Maste                                                     true,           // Run IOHandler in async mode
2290127ef0fSEd Maste                                                     &bp_options_vec);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
230ac7ddfbfSEd Maste     }
231ac7ddfbfSEd Maste 
232ac7ddfbfSEd Maste     /// Set a one-liner as the callback for the breakpoint.
233ac7ddfbfSEd Maste     void
2340127ef0fSEd Maste     SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
235ac7ddfbfSEd Maste                                   const char *oneliner)
236ac7ddfbfSEd Maste     {
2370127ef0fSEd Maste         for (auto bp_options : bp_options_vec)
2380127ef0fSEd Maste         {
239ac7ddfbfSEd Maste             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
240ac7ddfbfSEd Maste 
241ac7ddfbfSEd Maste             // It's necessary to set both user_source and script_source to the oneliner.
242ac7ddfbfSEd Maste             // The former is used to generate callback description (as in breakpoint command list)
243ac7ddfbfSEd Maste             // while the latter is used for Python to interpret during the actual callback.
244ac7ddfbfSEd Maste             data_ap->user_source.AppendString (oneliner);
245ac7ddfbfSEd Maste             data_ap->script_source.assign (oneliner);
246ac7ddfbfSEd Maste             data_ap->stop_on_error = m_options.m_stop_on_error;
247ac7ddfbfSEd Maste 
248ac7ddfbfSEd Maste             BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
249ac7ddfbfSEd Maste             bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
2500127ef0fSEd Maste         }
251ac7ddfbfSEd Maste         return;
252ac7ddfbfSEd Maste     }
253ac7ddfbfSEd Maste 
254ac7ddfbfSEd Maste     static bool
255ac7ddfbfSEd Maste     BreakpointOptionsCallbackFunction (void *baton,
256ac7ddfbfSEd Maste                                        StoppointCallbackContext *context,
257ac7ddfbfSEd Maste                                        lldb::user_id_t break_id,
258ac7ddfbfSEd Maste                                        lldb::user_id_t break_loc_id)
259ac7ddfbfSEd Maste     {
260ac7ddfbfSEd Maste         bool ret_value = true;
261ac7ddfbfSEd Maste         if (baton == NULL)
262ac7ddfbfSEd Maste             return true;
263ac7ddfbfSEd Maste 
264ac7ddfbfSEd Maste 
265ac7ddfbfSEd Maste         BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
266ac7ddfbfSEd Maste         StringList &commands = data->user_source;
267ac7ddfbfSEd Maste 
268ac7ddfbfSEd Maste         if (commands.GetSize() > 0)
269ac7ddfbfSEd Maste         {
270ac7ddfbfSEd Maste             ExecutionContext exe_ctx (context->exe_ctx_ref);
271ac7ddfbfSEd Maste             Target *target = exe_ctx.GetTargetPtr();
272ac7ddfbfSEd Maste             if (target)
273ac7ddfbfSEd Maste             {
274ac7ddfbfSEd Maste                 CommandReturnObject result;
275ac7ddfbfSEd Maste                 Debugger &debugger = target->GetDebugger();
276ac7ddfbfSEd Maste                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
277ac7ddfbfSEd Maste                 // if the debugger is set up that way.
278ac7ddfbfSEd Maste 
279ac7ddfbfSEd Maste                 StreamSP output_stream (debugger.GetAsyncOutputStream());
280ac7ddfbfSEd Maste                 StreamSP error_stream (debugger.GetAsyncErrorStream());
281ac7ddfbfSEd Maste                 result.SetImmediateOutputStream (output_stream);
282ac7ddfbfSEd Maste                 result.SetImmediateErrorStream (error_stream);
283ac7ddfbfSEd Maste 
2847aa51b79SEd Maste                 CommandInterpreterRunOptions options;
2857aa51b79SEd Maste                 options.SetStopOnContinue(true);
2867aa51b79SEd Maste                 options.SetStopOnError (data->stop_on_error);
2877aa51b79SEd Maste                 options.SetEchoCommands (true);
2887aa51b79SEd Maste                 options.SetPrintResults (true);
2897aa51b79SEd Maste                 options.SetAddToHistory (false);
290ac7ddfbfSEd Maste 
291ac7ddfbfSEd Maste                 debugger.GetCommandInterpreter().HandleCommands (commands,
292ac7ddfbfSEd Maste                                                                  &exe_ctx,
2937aa51b79SEd Maste                                                                  options,
294ac7ddfbfSEd Maste                                                                  result);
295ac7ddfbfSEd Maste                 result.GetImmediateOutputStream()->Flush();
296ac7ddfbfSEd Maste                 result.GetImmediateErrorStream()->Flush();
297ac7ddfbfSEd Maste            }
298ac7ddfbfSEd Maste         }
299ac7ddfbfSEd Maste         return ret_value;
300ac7ddfbfSEd Maste     }
301ac7ddfbfSEd Maste 
302ac7ddfbfSEd Maste     class CommandOptions : public Options
303ac7ddfbfSEd Maste     {
304ac7ddfbfSEd Maste     public:
305ac7ddfbfSEd Maste 
306ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
307ac7ddfbfSEd Maste             Options (interpreter),
308ac7ddfbfSEd Maste             m_use_commands (false),
309ac7ddfbfSEd Maste             m_use_script_language (false),
310ac7ddfbfSEd Maste             m_script_language (eScriptLanguageNone),
311ac7ddfbfSEd Maste             m_use_one_liner (false),
312ac7ddfbfSEd Maste             m_one_liner(),
313ac7ddfbfSEd Maste             m_function_name()
314ac7ddfbfSEd Maste         {
315ac7ddfbfSEd Maste         }
316ac7ddfbfSEd Maste 
3179f2f44ceSEd Maste         ~CommandOptions () override {}
318ac7ddfbfSEd Maste 
3199f2f44ceSEd Maste         Error
3209f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
321ac7ddfbfSEd Maste         {
322ac7ddfbfSEd Maste             Error error;
323ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
324ac7ddfbfSEd Maste 
325ac7ddfbfSEd Maste             switch (short_option)
326ac7ddfbfSEd Maste             {
327ac7ddfbfSEd Maste             case 'o':
328ac7ddfbfSEd Maste                 m_use_one_liner = true;
329ac7ddfbfSEd Maste                 m_one_liner = option_arg;
330ac7ddfbfSEd Maste                 break;
331ac7ddfbfSEd Maste 
332ac7ddfbfSEd Maste             case 's':
333ac7ddfbfSEd Maste                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
334ac7ddfbfSEd Maste                                                                                      g_option_table[option_idx].enum_values,
335ac7ddfbfSEd Maste                                                                                      eScriptLanguageNone,
336ac7ddfbfSEd Maste                                                                                      error);
337ac7ddfbfSEd Maste 
338ac7ddfbfSEd Maste                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
339ac7ddfbfSEd Maste                 {
340ac7ddfbfSEd Maste                     m_use_script_language = true;
341ac7ddfbfSEd Maste                 }
342ac7ddfbfSEd Maste                 else
343ac7ddfbfSEd Maste                 {
344ac7ddfbfSEd Maste                     m_use_script_language = false;
345ac7ddfbfSEd Maste                 }
346ac7ddfbfSEd Maste                 break;
347ac7ddfbfSEd Maste 
348ac7ddfbfSEd Maste             case 'e':
349ac7ddfbfSEd Maste                 {
350ac7ddfbfSEd Maste                     bool success = false;
351ac7ddfbfSEd Maste                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
352ac7ddfbfSEd Maste                     if (!success)
353ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
354ac7ddfbfSEd Maste                 }
355ac7ddfbfSEd Maste                 break;
356ac7ddfbfSEd Maste 
357ac7ddfbfSEd Maste             case 'F':
358ac7ddfbfSEd Maste                 {
359ac7ddfbfSEd Maste                     m_use_one_liner = false;
360ac7ddfbfSEd Maste                     m_use_script_language = true;
361ac7ddfbfSEd Maste                     m_function_name.assign(option_arg);
362ac7ddfbfSEd Maste                 }
363ac7ddfbfSEd Maste                 break;
364ac7ddfbfSEd Maste 
3657aa51b79SEd Maste             case 'D':
3667aa51b79SEd Maste                 m_use_dummy = true;
3677aa51b79SEd Maste                 break;
3687aa51b79SEd Maste 
369ac7ddfbfSEd Maste             default:
370ac7ddfbfSEd Maste                 break;
371ac7ddfbfSEd Maste             }
372ac7ddfbfSEd Maste             return error;
373ac7ddfbfSEd Maste         }
374ac7ddfbfSEd Maste         void
3759f2f44ceSEd Maste         OptionParsingStarting () override
376ac7ddfbfSEd Maste         {
377ac7ddfbfSEd Maste             m_use_commands = true;
378ac7ddfbfSEd Maste             m_use_script_language = false;
379ac7ddfbfSEd Maste             m_script_language = eScriptLanguageNone;
380ac7ddfbfSEd Maste 
381ac7ddfbfSEd Maste             m_use_one_liner = false;
382ac7ddfbfSEd Maste             m_stop_on_error = true;
383ac7ddfbfSEd Maste             m_one_liner.clear();
384ac7ddfbfSEd Maste             m_function_name.clear();
3857aa51b79SEd Maste             m_use_dummy = false;
386ac7ddfbfSEd Maste         }
387ac7ddfbfSEd Maste 
388ac7ddfbfSEd Maste         const OptionDefinition*
3899f2f44ceSEd Maste         GetDefinitions () override
390ac7ddfbfSEd Maste         {
391ac7ddfbfSEd Maste             return g_option_table;
392ac7ddfbfSEd Maste         }
393ac7ddfbfSEd Maste 
394ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
395ac7ddfbfSEd Maste 
396ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
397ac7ddfbfSEd Maste 
398ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
399ac7ddfbfSEd Maste 
400ac7ddfbfSEd Maste         bool m_use_commands;
401ac7ddfbfSEd Maste         bool m_use_script_language;
402ac7ddfbfSEd Maste         lldb::ScriptLanguage m_script_language;
403ac7ddfbfSEd Maste 
404ac7ddfbfSEd Maste         // Instance variables to hold the values for one_liner options.
405ac7ddfbfSEd Maste         bool m_use_one_liner;
406ac7ddfbfSEd Maste         std::string m_one_liner;
407ac7ddfbfSEd Maste         bool m_stop_on_error;
408ac7ddfbfSEd Maste         std::string m_function_name;
4097aa51b79SEd Maste         bool m_use_dummy;
410ac7ddfbfSEd Maste     };
411ac7ddfbfSEd Maste 
412ac7ddfbfSEd Maste protected:
4139f2f44ceSEd Maste     bool
4149f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
415ac7ddfbfSEd Maste     {
4167aa51b79SEd Maste         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
417ac7ddfbfSEd Maste 
418ac7ddfbfSEd Maste         if (target == NULL)
419ac7ddfbfSEd Maste         {
420ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
421ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
422ac7ddfbfSEd Maste             return false;
423ac7ddfbfSEd Maste         }
424ac7ddfbfSEd Maste 
425ac7ddfbfSEd Maste         const BreakpointList &breakpoints = target->GetBreakpointList();
426ac7ddfbfSEd Maste         size_t num_breakpoints = breakpoints.GetSize();
427ac7ddfbfSEd Maste 
428ac7ddfbfSEd Maste         if (num_breakpoints == 0)
429ac7ddfbfSEd Maste         {
430ac7ddfbfSEd Maste             result.AppendError ("No breakpoints exist to have commands added");
431ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
432ac7ddfbfSEd Maste             return false;
433ac7ddfbfSEd Maste         }
434ac7ddfbfSEd Maste 
435ac7ddfbfSEd Maste         if (m_options.m_use_script_language == false && m_options.m_function_name.size())
436ac7ddfbfSEd Maste         {
437ac7ddfbfSEd Maste             result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
438ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
439ac7ddfbfSEd Maste             return false;
440ac7ddfbfSEd Maste         }
441ac7ddfbfSEd Maste 
442ac7ddfbfSEd Maste         BreakpointIDList valid_bp_ids;
4437aa51b79SEd Maste         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
444ac7ddfbfSEd Maste 
4450127ef0fSEd Maste         m_bp_options_vec.clear();
4460127ef0fSEd Maste 
447ac7ddfbfSEd Maste         if (result.Succeeded())
448ac7ddfbfSEd Maste         {
449ac7ddfbfSEd Maste             const size_t count = valid_bp_ids.GetSize();
450ac7ddfbfSEd Maste 
451ac7ddfbfSEd Maste             for (size_t i = 0; i < count; ++i)
452ac7ddfbfSEd Maste             {
453ac7ddfbfSEd Maste                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
454ac7ddfbfSEd Maste                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
455ac7ddfbfSEd Maste                 {
456ac7ddfbfSEd Maste                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
457ac7ddfbfSEd Maste                     BreakpointOptions *bp_options = NULL;
458ac7ddfbfSEd Maste                     if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
459ac7ddfbfSEd Maste                     {
460ac7ddfbfSEd Maste                         // This breakpoint does not have an associated location.
461ac7ddfbfSEd Maste                         bp_options = bp->GetOptions();
462ac7ddfbfSEd Maste                     }
463ac7ddfbfSEd Maste                     else
464ac7ddfbfSEd Maste                     {
465ac7ddfbfSEd Maste                         BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
466ac7ddfbfSEd Maste                         // This breakpoint does have an associated location.
467ac7ddfbfSEd Maste                         // Get its breakpoint options.
468ac7ddfbfSEd Maste                         if (bp_loc_sp)
469ac7ddfbfSEd Maste                             bp_options = bp_loc_sp->GetLocationOptions();
470ac7ddfbfSEd Maste                     }
4710127ef0fSEd Maste                     if (bp_options)
4720127ef0fSEd Maste                         m_bp_options_vec.push_back (bp_options);
4730127ef0fSEd Maste                 }
4740127ef0fSEd Maste             }
475ac7ddfbfSEd Maste 
476ac7ddfbfSEd Maste             // If we are using script language, get the script interpreter
477ac7ddfbfSEd Maste             // in order to set or collect command callback.  Otherwise, call
478ac7ddfbfSEd Maste             // the methods associated with this object.
479ac7ddfbfSEd Maste             if (m_options.m_use_script_language)
480ac7ddfbfSEd Maste             {
4810127ef0fSEd Maste                 ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
482ac7ddfbfSEd Maste                 // Special handling for one-liner specified inline.
483ac7ddfbfSEd Maste                 if (m_options.m_use_one_liner)
484ac7ddfbfSEd Maste                 {
4850127ef0fSEd Maste                     script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
486ac7ddfbfSEd Maste                                                                  m_options.m_one_liner.c_str());
487ac7ddfbfSEd Maste                 }
488ac7ddfbfSEd Maste                 else if (m_options.m_function_name.size())
489ac7ddfbfSEd Maste                 {
4900127ef0fSEd Maste                     script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
4910127ef0fSEd Maste                                                                          m_options.m_function_name.c_str());
492ac7ddfbfSEd Maste                 }
493ac7ddfbfSEd Maste                 else
494ac7ddfbfSEd Maste                 {
4950127ef0fSEd Maste                     script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
496ac7ddfbfSEd Maste                                                                             result);
497ac7ddfbfSEd Maste                 }
498ac7ddfbfSEd Maste             }
499ac7ddfbfSEd Maste             else
500ac7ddfbfSEd Maste             {
501ac7ddfbfSEd Maste                 // Special handling for one-liner specified inline.
502ac7ddfbfSEd Maste                 if (m_options.m_use_one_liner)
5030127ef0fSEd Maste                     SetBreakpointCommandCallback (m_bp_options_vec,
504ac7ddfbfSEd Maste                                                   m_options.m_one_liner.c_str());
505ac7ddfbfSEd Maste                 else
5060127ef0fSEd Maste                     CollectDataForBreakpointCommandCallback (m_bp_options_vec,
507ac7ddfbfSEd Maste                                                              result);
508ac7ddfbfSEd Maste             }
5090127ef0fSEd Maste 
510ac7ddfbfSEd Maste         }
511ac7ddfbfSEd Maste 
512ac7ddfbfSEd Maste         return result.Succeeded();
513ac7ddfbfSEd Maste     }
514ac7ddfbfSEd Maste 
515ac7ddfbfSEd Maste private:
516ac7ddfbfSEd Maste     CommandOptions m_options;
5170127ef0fSEd Maste     std::vector<BreakpointOptions *> m_bp_options_vec;  // This stores the breakpoint options that we are currently
5180127ef0fSEd Maste                                                         // collecting commands for.  In the CollectData... calls we need
5190127ef0fSEd Maste                                                         // to hand this off to the IOHandler, which may run asynchronously.
5200127ef0fSEd Maste                                                         // So we have to have some way to keep it alive, and not leak it.
5210127ef0fSEd Maste                                                         // Making it an ivar of the command object, which never goes away
5220127ef0fSEd Maste                                                         // achieves this.  Note that if we were able to run
5230127ef0fSEd Maste                                                         // the same command concurrently in one interpreter we'd have to
5240127ef0fSEd Maste                                                         // make this "per invocation".  But there are many more reasons
5250127ef0fSEd Maste                                                         // why it is not in general safe to do that in lldb at present,
5260127ef0fSEd Maste                                                         // so it isn't worthwhile to come up with a more complex mechanism
5270127ef0fSEd Maste                                                         // to address this particular weakness right now.
528ac7ddfbfSEd Maste     static const char *g_reader_instructions;
529ac7ddfbfSEd Maste 
530ac7ddfbfSEd Maste };
531ac7ddfbfSEd Maste 
532ac7ddfbfSEd Maste const char *
53312b93ac6SEd Maste CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.\n";
534ac7ddfbfSEd Maste 
535ac7ddfbfSEd Maste // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
536ac7ddfbfSEd Maste // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
537ac7ddfbfSEd Maste 
538ac7ddfbfSEd Maste static OptionEnumValueElement
539ac7ddfbfSEd Maste g_script_option_enumeration[4] =
540ac7ddfbfSEd Maste {
541ac7ddfbfSEd Maste     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
542ac7ddfbfSEd Maste     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
543ac7ddfbfSEd Maste     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
544ac7ddfbfSEd Maste     { 0,                      NULL,              NULL }
545ac7ddfbfSEd Maste };
546ac7ddfbfSEd Maste 
547ac7ddfbfSEd Maste OptionDefinition
548ac7ddfbfSEd Maste CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
549ac7ddfbfSEd Maste {
5500127ef0fSEd Maste     { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
551ac7ddfbfSEd Maste         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
552ac7ddfbfSEd Maste 
5530127ef0fSEd Maste     { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
554ac7ddfbfSEd Maste         "Specify whether breakpoint command execution should terminate on error." },
555ac7ddfbfSEd Maste 
5560127ef0fSEd Maste     { LLDB_OPT_SET_ALL,   false, "script-type",     's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
557ac7ddfbfSEd Maste         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
558ac7ddfbfSEd Maste 
5590127ef0fSEd Maste     { LLDB_OPT_SET_2,   false, "python-function",     'F', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction,
560ac7ddfbfSEd Maste         "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
561ac7ddfbfSEd Maste 
5627aa51b79SEd Maste     { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
5637aa51b79SEd Maste         "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
5647aa51b79SEd Maste 
5650127ef0fSEd Maste     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
566ac7ddfbfSEd Maste };
567ac7ddfbfSEd Maste 
568ac7ddfbfSEd Maste //-------------------------------------------------------------------------
569ac7ddfbfSEd Maste // CommandObjectBreakpointCommandDelete
570ac7ddfbfSEd Maste //-------------------------------------------------------------------------
571ac7ddfbfSEd Maste 
572ac7ddfbfSEd Maste class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
573ac7ddfbfSEd Maste {
574ac7ddfbfSEd Maste public:
575ac7ddfbfSEd Maste     CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
576ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
577ac7ddfbfSEd Maste                              "delete",
578ac7ddfbfSEd Maste                              "Delete the set of commands from a breakpoint.",
5797aa51b79SEd Maste                              NULL),
5807aa51b79SEd Maste         m_options (interpreter)
581ac7ddfbfSEd Maste     {
582ac7ddfbfSEd Maste         CommandArgumentEntry arg;
583ac7ddfbfSEd Maste         CommandArgumentData bp_id_arg;
584ac7ddfbfSEd Maste 
585ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
586ac7ddfbfSEd Maste         bp_id_arg.arg_type = eArgTypeBreakpointID;
587ac7ddfbfSEd Maste         bp_id_arg.arg_repetition = eArgRepeatPlain;
588ac7ddfbfSEd Maste 
589ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
590ac7ddfbfSEd Maste         arg.push_back (bp_id_arg);
591ac7ddfbfSEd Maste 
592ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
593ac7ddfbfSEd Maste         m_arguments.push_back (arg);
594ac7ddfbfSEd Maste     }
595ac7ddfbfSEd Maste 
596ac7ddfbfSEd Maste 
5979f2f44ceSEd Maste     ~CommandObjectBreakpointCommandDelete () override {}
598ac7ddfbfSEd Maste 
5999f2f44ceSEd Maste     Options *
6009f2f44ceSEd Maste     GetOptions () override
6017aa51b79SEd Maste     {
6027aa51b79SEd Maste         return &m_options;
6037aa51b79SEd Maste     }
6047aa51b79SEd Maste 
6057aa51b79SEd Maste     class CommandOptions : public Options
6067aa51b79SEd Maste     {
6077aa51b79SEd Maste     public:
6087aa51b79SEd Maste 
6097aa51b79SEd Maste         CommandOptions (CommandInterpreter &interpreter) :
6107aa51b79SEd Maste             Options (interpreter),
6117aa51b79SEd Maste             m_use_dummy (false)
6127aa51b79SEd Maste         {
6137aa51b79SEd Maste         }
6147aa51b79SEd Maste 
6159f2f44ceSEd Maste         ~CommandOptions () override {}
6167aa51b79SEd Maste 
6179f2f44ceSEd Maste         Error
6189f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
6197aa51b79SEd Maste         {
6207aa51b79SEd Maste             Error error;
6217aa51b79SEd Maste             const int short_option = m_getopt_table[option_idx].val;
6227aa51b79SEd Maste 
6237aa51b79SEd Maste             switch (short_option)
6247aa51b79SEd Maste             {
6257aa51b79SEd Maste                 case 'D':
6267aa51b79SEd Maste                     m_use_dummy = true;
6277aa51b79SEd Maste                     break;
6287aa51b79SEd Maste 
6297aa51b79SEd Maste                 default:
6307aa51b79SEd Maste                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
6317aa51b79SEd Maste                     break;
6327aa51b79SEd Maste             }
6337aa51b79SEd Maste 
6347aa51b79SEd Maste             return error;
6357aa51b79SEd Maste         }
6367aa51b79SEd Maste 
6377aa51b79SEd Maste         void
6389f2f44ceSEd Maste         OptionParsingStarting () override
6397aa51b79SEd Maste         {
6407aa51b79SEd Maste             m_use_dummy = false;
6417aa51b79SEd Maste         }
6427aa51b79SEd Maste 
6437aa51b79SEd Maste         const OptionDefinition*
6449f2f44ceSEd Maste         GetDefinitions () override
6457aa51b79SEd Maste         {
6467aa51b79SEd Maste             return g_option_table;
6477aa51b79SEd Maste         }
6487aa51b79SEd Maste 
6497aa51b79SEd Maste         // Options table: Required for subclasses of Options.
6507aa51b79SEd Maste 
6517aa51b79SEd Maste         static OptionDefinition g_option_table[];
6527aa51b79SEd Maste 
6537aa51b79SEd Maste         // Instance variables to hold the values for command options.
6547aa51b79SEd Maste         bool m_use_dummy;
6557aa51b79SEd Maste     };
6567aa51b79SEd Maste 
657ac7ddfbfSEd Maste protected:
6589f2f44ceSEd Maste     bool
6599f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
660ac7ddfbfSEd Maste     {
6617aa51b79SEd Maste         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
662ac7ddfbfSEd Maste 
663ac7ddfbfSEd Maste         if (target == NULL)
664ac7ddfbfSEd Maste         {
665ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
666ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
667ac7ddfbfSEd Maste             return false;
668ac7ddfbfSEd Maste         }
669ac7ddfbfSEd Maste 
670ac7ddfbfSEd Maste         const BreakpointList &breakpoints = target->GetBreakpointList();
671ac7ddfbfSEd Maste         size_t num_breakpoints = breakpoints.GetSize();
672ac7ddfbfSEd Maste 
673ac7ddfbfSEd Maste         if (num_breakpoints == 0)
674ac7ddfbfSEd Maste         {
675ac7ddfbfSEd Maste             result.AppendError ("No breakpoints exist to have commands deleted");
676ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
677ac7ddfbfSEd Maste             return false;
678ac7ddfbfSEd Maste         }
679ac7ddfbfSEd Maste 
680ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
681ac7ddfbfSEd Maste         {
682ac7ddfbfSEd Maste             result.AppendError ("No breakpoint specified from which to delete the commands");
683ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
684ac7ddfbfSEd Maste             return false;
685ac7ddfbfSEd Maste         }
686ac7ddfbfSEd Maste 
687ac7ddfbfSEd Maste         BreakpointIDList valid_bp_ids;
6887aa51b79SEd Maste         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
689ac7ddfbfSEd Maste 
690ac7ddfbfSEd Maste         if (result.Succeeded())
691ac7ddfbfSEd Maste         {
692ac7ddfbfSEd Maste             const size_t count = valid_bp_ids.GetSize();
693ac7ddfbfSEd Maste             for (size_t i = 0; i < count; ++i)
694ac7ddfbfSEd Maste             {
695ac7ddfbfSEd Maste                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
696ac7ddfbfSEd Maste                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
697ac7ddfbfSEd Maste                 {
698ac7ddfbfSEd Maste                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
699ac7ddfbfSEd Maste                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
700ac7ddfbfSEd Maste                     {
701ac7ddfbfSEd Maste                         BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
702ac7ddfbfSEd Maste                         if (bp_loc_sp)
703ac7ddfbfSEd Maste                             bp_loc_sp->ClearCallback();
704ac7ddfbfSEd Maste                         else
705ac7ddfbfSEd Maste                         {
706ac7ddfbfSEd Maste                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
707ac7ddfbfSEd Maste                                                          cur_bp_id.GetBreakpointID(),
708ac7ddfbfSEd Maste                                                          cur_bp_id.GetLocationID());
709ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
710ac7ddfbfSEd Maste                             return false;
711ac7ddfbfSEd Maste                         }
712ac7ddfbfSEd Maste                     }
713ac7ddfbfSEd Maste                     else
714ac7ddfbfSEd Maste                     {
715ac7ddfbfSEd Maste                         bp->ClearCallback();
716ac7ddfbfSEd Maste                     }
717ac7ddfbfSEd Maste                 }
718ac7ddfbfSEd Maste             }
719ac7ddfbfSEd Maste         }
720ac7ddfbfSEd Maste         return result.Succeeded();
721ac7ddfbfSEd Maste     }
7227aa51b79SEd Maste private:
7237aa51b79SEd Maste     CommandOptions m_options;
724ac7ddfbfSEd Maste };
725ac7ddfbfSEd Maste 
7267aa51b79SEd Maste OptionDefinition
7277aa51b79SEd Maste CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
7287aa51b79SEd Maste {
7297aa51b79SEd Maste     { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
7307aa51b79SEd Maste         "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
7317aa51b79SEd Maste 
7327aa51b79SEd Maste     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
7337aa51b79SEd Maste };
7347aa51b79SEd Maste 
7357aa51b79SEd Maste 
736ac7ddfbfSEd Maste //-------------------------------------------------------------------------
737ac7ddfbfSEd Maste // CommandObjectBreakpointCommandList
738ac7ddfbfSEd Maste //-------------------------------------------------------------------------
739ac7ddfbfSEd Maste 
740ac7ddfbfSEd Maste class CommandObjectBreakpointCommandList : public CommandObjectParsed
741ac7ddfbfSEd Maste {
742ac7ddfbfSEd Maste public:
743ac7ddfbfSEd Maste     CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
744ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
745ac7ddfbfSEd Maste                              "list",
746ac7ddfbfSEd Maste                              "List the script or set of commands to be executed when the breakpoint is hit.",
747ac7ddfbfSEd Maste                               NULL)
748ac7ddfbfSEd Maste     {
749ac7ddfbfSEd Maste         CommandArgumentEntry arg;
750ac7ddfbfSEd Maste         CommandArgumentData bp_id_arg;
751ac7ddfbfSEd Maste 
752ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
753ac7ddfbfSEd Maste         bp_id_arg.arg_type = eArgTypeBreakpointID;
754ac7ddfbfSEd Maste         bp_id_arg.arg_repetition = eArgRepeatPlain;
755ac7ddfbfSEd Maste 
756ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
757ac7ddfbfSEd Maste         arg.push_back (bp_id_arg);
758ac7ddfbfSEd Maste 
759ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
760ac7ddfbfSEd Maste         m_arguments.push_back (arg);
761ac7ddfbfSEd Maste     }
762ac7ddfbfSEd Maste 
7639f2f44ceSEd Maste     ~CommandObjectBreakpointCommandList () override {}
764ac7ddfbfSEd Maste 
765ac7ddfbfSEd Maste protected:
7669f2f44ceSEd Maste     bool
767ac7ddfbfSEd Maste     DoExecute (Args& command,
7689f2f44ceSEd Maste              CommandReturnObject &result) override
769ac7ddfbfSEd Maste     {
770ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
771ac7ddfbfSEd Maste 
772ac7ddfbfSEd Maste         if (target == NULL)
773ac7ddfbfSEd Maste         {
774ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
775ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
776ac7ddfbfSEd Maste             return false;
777ac7ddfbfSEd Maste         }
778ac7ddfbfSEd Maste 
779ac7ddfbfSEd Maste         const BreakpointList &breakpoints = target->GetBreakpointList();
780ac7ddfbfSEd Maste         size_t num_breakpoints = breakpoints.GetSize();
781ac7ddfbfSEd Maste 
782ac7ddfbfSEd Maste         if (num_breakpoints == 0)
783ac7ddfbfSEd Maste         {
784ac7ddfbfSEd Maste             result.AppendError ("No breakpoints exist for which to list commands");
785ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
786ac7ddfbfSEd Maste             return false;
787ac7ddfbfSEd Maste         }
788ac7ddfbfSEd Maste 
789ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
790ac7ddfbfSEd Maste         {
791ac7ddfbfSEd Maste             result.AppendError ("No breakpoint specified for which to list the commands");
792ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
793ac7ddfbfSEd Maste             return false;
794ac7ddfbfSEd Maste         }
795ac7ddfbfSEd Maste 
796ac7ddfbfSEd Maste         BreakpointIDList valid_bp_ids;
7977aa51b79SEd Maste         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
798ac7ddfbfSEd Maste 
799ac7ddfbfSEd Maste         if (result.Succeeded())
800ac7ddfbfSEd Maste         {
801ac7ddfbfSEd Maste             const size_t count = valid_bp_ids.GetSize();
802ac7ddfbfSEd Maste             for (size_t i = 0; i < count; ++i)
803ac7ddfbfSEd Maste             {
804ac7ddfbfSEd Maste                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
805ac7ddfbfSEd Maste                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
806ac7ddfbfSEd Maste                 {
807ac7ddfbfSEd Maste                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
808ac7ddfbfSEd Maste 
809ac7ddfbfSEd Maste                     if (bp)
810ac7ddfbfSEd Maste                     {
811ac7ddfbfSEd Maste                         const BreakpointOptions *bp_options = NULL;
812ac7ddfbfSEd Maste                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
813ac7ddfbfSEd Maste                         {
814ac7ddfbfSEd Maste                             BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
815ac7ddfbfSEd Maste                             if (bp_loc_sp)
816ac7ddfbfSEd Maste                                 bp_options = bp_loc_sp->GetOptionsNoCreate();
817ac7ddfbfSEd Maste                             else
818ac7ddfbfSEd Maste                             {
819ac7ddfbfSEd Maste                                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
820ac7ddfbfSEd Maste                                                              cur_bp_id.GetBreakpointID(),
821ac7ddfbfSEd Maste                                                              cur_bp_id.GetLocationID());
822ac7ddfbfSEd Maste                                 result.SetStatus (eReturnStatusFailed);
823ac7ddfbfSEd Maste                                 return false;
824ac7ddfbfSEd Maste                             }
825ac7ddfbfSEd Maste                         }
826ac7ddfbfSEd Maste                         else
827ac7ddfbfSEd Maste                         {
828ac7ddfbfSEd Maste                             bp_options = bp->GetOptions();
829ac7ddfbfSEd Maste                         }
830ac7ddfbfSEd Maste 
831ac7ddfbfSEd Maste                         if (bp_options)
832ac7ddfbfSEd Maste                         {
833ac7ddfbfSEd Maste                             StreamString id_str;
834ac7ddfbfSEd Maste                             BreakpointID::GetCanonicalReference (&id_str,
835ac7ddfbfSEd Maste                                                                  cur_bp_id.GetBreakpointID(),
836ac7ddfbfSEd Maste                                                                  cur_bp_id.GetLocationID());
837ac7ddfbfSEd Maste                             const Baton *baton = bp_options->GetBaton();
838ac7ddfbfSEd Maste                             if (baton)
839ac7ddfbfSEd Maste                             {
840ac7ddfbfSEd Maste                                 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
841ac7ddfbfSEd Maste                                 result.GetOutputStream().IndentMore ();
842ac7ddfbfSEd Maste                                 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
843ac7ddfbfSEd Maste                                 result.GetOutputStream().IndentLess ();
844ac7ddfbfSEd Maste                             }
845ac7ddfbfSEd Maste                             else
846ac7ddfbfSEd Maste                             {
847ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
848ac7ddfbfSEd Maste                                                                 id_str.GetData());
849ac7ddfbfSEd Maste                             }
850ac7ddfbfSEd Maste                         }
851ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusSuccessFinishResult);
852ac7ddfbfSEd Maste                     }
853ac7ddfbfSEd Maste                     else
854ac7ddfbfSEd Maste                     {
855ac7ddfbfSEd Maste                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
856ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
857ac7ddfbfSEd Maste                     }
858ac7ddfbfSEd Maste 
859ac7ddfbfSEd Maste                 }
860ac7ddfbfSEd Maste             }
861ac7ddfbfSEd Maste         }
862ac7ddfbfSEd Maste 
863ac7ddfbfSEd Maste         return result.Succeeded();
864ac7ddfbfSEd Maste     }
865ac7ddfbfSEd Maste };
866ac7ddfbfSEd Maste 
867ac7ddfbfSEd Maste //-------------------------------------------------------------------------
868ac7ddfbfSEd Maste // CommandObjectBreakpointCommand
869ac7ddfbfSEd Maste //-------------------------------------------------------------------------
870ac7ddfbfSEd Maste 
871ac7ddfbfSEd Maste CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
872ac7ddfbfSEd Maste     CommandObjectMultiword (interpreter,
873ac7ddfbfSEd Maste                             "command",
8740127ef0fSEd Maste                             "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
875ac7ddfbfSEd Maste                             "command <sub-command> [<sub-command-options>] <breakpoint-id>")
876ac7ddfbfSEd Maste {
877ac7ddfbfSEd Maste     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
878ac7ddfbfSEd Maste     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
879ac7ddfbfSEd Maste     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
880ac7ddfbfSEd Maste 
881ac7ddfbfSEd Maste     add_command_object->SetCommandName ("breakpoint command add");
882ac7ddfbfSEd Maste     delete_command_object->SetCommandName ("breakpoint command delete");
883ac7ddfbfSEd Maste     list_command_object->SetCommandName ("breakpoint command list");
884ac7ddfbfSEd Maste 
885ac7ddfbfSEd Maste     LoadSubCommand ("add",    add_command_object);
886ac7ddfbfSEd Maste     LoadSubCommand ("delete", delete_command_object);
887ac7ddfbfSEd Maste     LoadSubCommand ("list",   list_command_object);
888ac7ddfbfSEd Maste }
889ac7ddfbfSEd Maste 
890ac7ddfbfSEd Maste CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
891ac7ddfbfSEd Maste {
892ac7ddfbfSEd Maste }
893ac7ddfbfSEd Maste 
894ac7ddfbfSEd Maste 
895