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
124bb0738eSEd Maste // Other libraries and framework includes
134bb0738eSEd Maste // Project includes
14ac7ddfbfSEd Maste #include "CommandObjectBreakpointCommand.h"
15ac7ddfbfSEd Maste #include "CommandObjectBreakpoint.h"
1612b93ac6SEd Maste #include "lldb/Core/IOHandler.h"
17ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
18ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
19ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
20ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
21ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointIDList.h"
22ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
23ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
24ac7ddfbfSEd Maste #include "lldb/Breakpoint/StoppointCallbackContext.h"
25ac7ddfbfSEd Maste #include "lldb/Core/State.h"
26ac7ddfbfSEd Maste 
27ac7ddfbfSEd Maste using namespace lldb;
28ac7ddfbfSEd Maste using namespace lldb_private;
29ac7ddfbfSEd Maste 
30ac7ddfbfSEd Maste //-------------------------------------------------------------------------
31ac7ddfbfSEd Maste // CommandObjectBreakpointCommandAdd
32ac7ddfbfSEd Maste //-------------------------------------------------------------------------
33ac7ddfbfSEd Maste 
3412b93ac6SEd Maste class CommandObjectBreakpointCommandAdd :
3512b93ac6SEd Maste     public CommandObjectParsed,
3612b93ac6SEd Maste     public IOHandlerDelegateMultiline
37ac7ddfbfSEd Maste {
38ac7ddfbfSEd Maste public:
394bb0738eSEd Maste     CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter)
404bb0738eSEd Maste         : CommandObjectParsed(interpreter, "add",
414bb0738eSEd Maste                               "Add LLDB commands to a breakpoint, to be executed whenever the breakpoint is hit."
420127ef0fSEd Maste                               "  If no breakpoint is specified, adds the commands to the last created breakpoint.",
434bb0738eSEd Maste                               nullptr),
4412b93ac6SEd Maste           IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand),
45ac7ddfbfSEd Maste           m_options(interpreter)
46ac7ddfbfSEd Maste     {
47ac7ddfbfSEd Maste         SetHelpLong (
48b91a7dfcSDimitry Andric R"(
49b91a7dfcSDimitry Andric General information about entering breakpoint commands
50b91a7dfcSDimitry Andric ------------------------------------------------------
51b91a7dfcSDimitry Andric 
52b91a7dfcSDimitry Andric )" "This command will prompt for commands to be executed when the specified \
53b91a7dfcSDimitry Andric breakpoint is hit.  Each command is typed on its own line following the '> ' \
54b91a7dfcSDimitry Andric prompt until 'DONE' is entered." R"(
55b91a7dfcSDimitry Andric 
56b91a7dfcSDimitry Andric )" "Syntactic errors may not be detected when initially entered, and many \
57b91a7dfcSDimitry Andric malformed commands can silently fail when executed.  If your breakpoint commands \
58b91a7dfcSDimitry Andric do not appear to be executing, double-check the command syntax." R"(
59b91a7dfcSDimitry Andric 
60b91a7dfcSDimitry Andric )" "Note: You may enter any debugger command exactly as you would at the debugger \
61b91a7dfcSDimitry Andric prompt.  There is no limit to the number of commands supplied, but do NOT enter \
62b91a7dfcSDimitry Andric more than one command per line." R"(
63b91a7dfcSDimitry Andric 
64b91a7dfcSDimitry Andric Special information about PYTHON breakpoint commands
65b91a7dfcSDimitry Andric ----------------------------------------------------
66b91a7dfcSDimitry Andric 
67b91a7dfcSDimitry Andric )" "You may enter either one or more lines of Python, including function \
68b91a7dfcSDimitry Andric definitions or calls to functions that will have been imported by the time \
69b91a7dfcSDimitry Andric the code executes.  Single line breakpoint commands will be interpreted 'as is' \
70b91a7dfcSDimitry Andric when the breakpoint is hit.  Multiple lines of Python will be wrapped in a \
71b91a7dfcSDimitry Andric generated function, and a call to the function will be attached to the breakpoint." R"(
72b91a7dfcSDimitry Andric 
73b91a7dfcSDimitry Andric This auto-generated function is passed in three arguments:
74b91a7dfcSDimitry Andric 
75b91a7dfcSDimitry Andric     frame:  an lldb.SBFrame object for the frame which hit breakpoint.
76b91a7dfcSDimitry Andric 
77b91a7dfcSDimitry Andric     bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
78b91a7dfcSDimitry Andric 
79b91a7dfcSDimitry Andric     dict:   the python session dictionary hit.
80b91a7dfcSDimitry Andric 
81b91a7dfcSDimitry Andric )" "When specifying a python function with the --python-function option, you need \
82b91a7dfcSDimitry Andric to supply the function name prepended by the module name:" R"(
83b91a7dfcSDimitry Andric 
84b91a7dfcSDimitry Andric     --python-function myutils.breakpoint_callback
85b91a7dfcSDimitry Andric 
86b91a7dfcSDimitry Andric The function itself must have the following prototype:
87b91a7dfcSDimitry Andric 
88b91a7dfcSDimitry Andric def breakpoint_callback(frame, bp_loc, dict):
89b91a7dfcSDimitry Andric   # Your code goes here
90b91a7dfcSDimitry Andric 
91b91a7dfcSDimitry Andric )" "The arguments are the same as the arguments passed to generated functions as \
92b91a7dfcSDimitry Andric described above.  Note that the global variable 'lldb.frame' will NOT be updated when \
93b91a7dfcSDimitry Andric this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
94b91a7dfcSDimitry Andric can get you to the thread via frame.GetThread(), the thread can get you to the \
95b91a7dfcSDimitry Andric process via thread.GetProcess(), and the process can get you back to the target \
96b91a7dfcSDimitry Andric via process.GetTarget()." R"(
97b91a7dfcSDimitry Andric 
98b91a7dfcSDimitry Andric )" "Important Note: As Python code gets collected into functions, access to global \
99b91a7dfcSDimitry Andric variables requires explicit scoping using the 'global' keyword.  Be sure to use correct \
100b91a7dfcSDimitry Andric Python syntax, including indentation, when entering Python breakpoint commands." R"(
101b91a7dfcSDimitry Andric 
102b91a7dfcSDimitry Andric Example Python one-line breakpoint command:
103b91a7dfcSDimitry Andric 
104b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1
105b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
106b91a7dfcSDimitry Andric > print "Hit this breakpoint!"
107b91a7dfcSDimitry Andric > DONE
108b91a7dfcSDimitry Andric 
109b91a7dfcSDimitry Andric As a convenience, this also works for a short Python one-liner:
110b91a7dfcSDimitry Andric 
111b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
112b91a7dfcSDimitry Andric (lldb) run
113b91a7dfcSDimitry Andric Launching '.../a.out'  (x86_64)
114b91a7dfcSDimitry Andric (lldb) Fri Sep 10 12:17:45 2010
115b91a7dfcSDimitry Andric Process 21778 Stopped
116b91a7dfcSDimitry Andric * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
117b91a7dfcSDimitry Andric   36
118b91a7dfcSDimitry Andric   37   	int c(int val)
119b91a7dfcSDimitry Andric   38   	{
120b91a7dfcSDimitry Andric   39 ->	    return val + 3;
121b91a7dfcSDimitry Andric   40   	}
122b91a7dfcSDimitry Andric   41
123b91a7dfcSDimitry Andric   42   	int main (int argc, char const *argv[])
124b91a7dfcSDimitry Andric 
125b91a7dfcSDimitry Andric Example multiple line Python breakpoint command:
126b91a7dfcSDimitry Andric 
127b91a7dfcSDimitry Andric (lldb) breakpoint command add -s p 1
128b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
129b91a7dfcSDimitry Andric > global bp_count
130b91a7dfcSDimitry Andric > bp_count = bp_count + 1
131b91a7dfcSDimitry Andric > print "Hit this breakpoint " + repr(bp_count) + " times!"
132b91a7dfcSDimitry Andric > DONE
133b91a7dfcSDimitry Andric 
134b91a7dfcSDimitry Andric Example multiple line Python breakpoint command, using function definition:
135b91a7dfcSDimitry Andric 
136b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1
137b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
138b91a7dfcSDimitry Andric > def breakpoint_output (bp_no):
139b91a7dfcSDimitry Andric >     out_string = "Hit breakpoint number " + repr (bp_no)
140b91a7dfcSDimitry Andric >     print out_string
141b91a7dfcSDimitry Andric >     return True
142b91a7dfcSDimitry Andric > breakpoint_output (1)
143b91a7dfcSDimitry Andric > DONE
144b91a7dfcSDimitry Andric 
145b91a7dfcSDimitry Andric )" "In this case, since there is a reference to a global variable, \
146b91a7dfcSDimitry Andric 'bp_count', you will also need to make sure 'bp_count' exists and is \
147b91a7dfcSDimitry Andric initialized:" R"(
148b91a7dfcSDimitry Andric 
149b91a7dfcSDimitry Andric (lldb) script
150b91a7dfcSDimitry Andric >>> bp_count = 0
151b91a7dfcSDimitry Andric >>> quit()
152b91a7dfcSDimitry Andric 
153b91a7dfcSDimitry Andric )" "Your Python code, however organized, can optionally return a value.  \
154b91a7dfcSDimitry Andric If the returned value is False, that tells LLDB not to stop at the breakpoint \
155b91a7dfcSDimitry Andric to which the code is associated. Returning anything other than False, or even \
156b91a7dfcSDimitry Andric returning None, or even omitting a return statement entirely, will cause \
157b91a7dfcSDimitry Andric LLDB to stop." R"(
158b91a7dfcSDimitry Andric 
159b91a7dfcSDimitry Andric )" "Final Note: A warning that no breakpoint command was generated when there \
160b91a7dfcSDimitry Andric are no syntax errors may indicate that a function was declared but never called."
161b91a7dfcSDimitry Andric         );
162ac7ddfbfSEd Maste 
163ac7ddfbfSEd Maste         CommandArgumentEntry arg;
164ac7ddfbfSEd Maste         CommandArgumentData bp_id_arg;
165ac7ddfbfSEd Maste 
166ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
167ac7ddfbfSEd Maste         bp_id_arg.arg_type = eArgTypeBreakpointID;
1680127ef0fSEd Maste         bp_id_arg.arg_repetition = eArgRepeatOptional;
169ac7ddfbfSEd Maste 
170ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
171ac7ddfbfSEd Maste         arg.push_back (bp_id_arg);
172ac7ddfbfSEd Maste 
173ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
174ac7ddfbfSEd Maste         m_arguments.push_back (arg);
175ac7ddfbfSEd Maste     }
176ac7ddfbfSEd Maste 
1774bb0738eSEd Maste     ~CommandObjectBreakpointCommandAdd() override = default;
178ac7ddfbfSEd Maste 
1799f2f44ceSEd Maste     Options *
1809f2f44ceSEd Maste     GetOptions () override
181ac7ddfbfSEd Maste     {
182ac7ddfbfSEd Maste         return &m_options;
183ac7ddfbfSEd Maste     }
184ac7ddfbfSEd Maste 
1859f2f44ceSEd Maste     void
1869f2f44ceSEd Maste     IOHandlerActivated (IOHandler &io_handler) override
18712b93ac6SEd Maste     {
18812b93ac6SEd Maste         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
18912b93ac6SEd Maste         if (output_sp)
19012b93ac6SEd Maste         {
19112b93ac6SEd Maste             output_sp->PutCString(g_reader_instructions);
19212b93ac6SEd Maste             output_sp->Flush();
19312b93ac6SEd Maste         }
19412b93ac6SEd Maste     }
19512b93ac6SEd Maste 
1969f2f44ceSEd Maste     void
1979f2f44ceSEd Maste     IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override
19812b93ac6SEd Maste     {
19912b93ac6SEd Maste         io_handler.SetIsDone(true);
20012b93ac6SEd Maste 
2010127ef0fSEd Maste         std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
2020127ef0fSEd Maste         for (BreakpointOptions *bp_options : *bp_options_vec)
20312b93ac6SEd Maste         {
2040127ef0fSEd Maste             if (!bp_options)
2050127ef0fSEd Maste                 continue;
2060127ef0fSEd Maste 
20712b93ac6SEd Maste             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
2084bb0738eSEd Maste             if (data_ap)
20912b93ac6SEd Maste             {
21012b93ac6SEd Maste                 data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
21112b93ac6SEd Maste                 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
21212b93ac6SEd Maste                 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
21312b93ac6SEd Maste             }
21412b93ac6SEd Maste         }
21512b93ac6SEd Maste     }
21612b93ac6SEd Maste 
217ac7ddfbfSEd Maste     void
2180127ef0fSEd Maste     CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
219ac7ddfbfSEd Maste                                              CommandReturnObject &result)
220ac7ddfbfSEd Maste     {
22112b93ac6SEd Maste         m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
22212b93ac6SEd Maste                                                     *this,          // IOHandlerDelegate
22312b93ac6SEd Maste                                                     true,           // Run IOHandler in async mode
2240127ef0fSEd Maste                                                     &bp_options_vec);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
225ac7ddfbfSEd Maste     }
226ac7ddfbfSEd Maste 
227ac7ddfbfSEd Maste     /// Set a one-liner as the callback for the breakpoint.
228ac7ddfbfSEd Maste     void
2290127ef0fSEd Maste     SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
230ac7ddfbfSEd Maste                                   const char *oneliner)
231ac7ddfbfSEd Maste     {
2320127ef0fSEd Maste         for (auto bp_options : bp_options_vec)
2330127ef0fSEd Maste         {
234ac7ddfbfSEd Maste             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
235ac7ddfbfSEd Maste 
236ac7ddfbfSEd Maste             // It's necessary to set both user_source and script_source to the oneliner.
237ac7ddfbfSEd Maste             // The former is used to generate callback description (as in breakpoint command list)
238ac7ddfbfSEd Maste             // while the latter is used for Python to interpret during the actual callback.
239ac7ddfbfSEd Maste             data_ap->user_source.AppendString (oneliner);
240ac7ddfbfSEd Maste             data_ap->script_source.assign (oneliner);
241ac7ddfbfSEd Maste             data_ap->stop_on_error = m_options.m_stop_on_error;
242ac7ddfbfSEd Maste 
243ac7ddfbfSEd Maste             BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
244ac7ddfbfSEd Maste             bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
2450127ef0fSEd Maste         }
246ac7ddfbfSEd Maste     }
247ac7ddfbfSEd Maste 
248ac7ddfbfSEd Maste     static bool
249ac7ddfbfSEd Maste     BreakpointOptionsCallbackFunction (void *baton,
250ac7ddfbfSEd Maste                                        StoppointCallbackContext *context,
251ac7ddfbfSEd Maste                                        lldb::user_id_t break_id,
252ac7ddfbfSEd Maste                                        lldb::user_id_t break_loc_id)
253ac7ddfbfSEd Maste     {
254ac7ddfbfSEd Maste         bool ret_value = true;
2554bb0738eSEd Maste         if (baton == nullptr)
256ac7ddfbfSEd Maste             return true;
257ac7ddfbfSEd Maste 
258ac7ddfbfSEd Maste         BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
259ac7ddfbfSEd Maste         StringList &commands = data->user_source;
260ac7ddfbfSEd Maste 
261ac7ddfbfSEd Maste         if (commands.GetSize() > 0)
262ac7ddfbfSEd Maste         {
263ac7ddfbfSEd Maste             ExecutionContext exe_ctx (context->exe_ctx_ref);
264ac7ddfbfSEd Maste             Target *target = exe_ctx.GetTargetPtr();
265ac7ddfbfSEd Maste             if (target)
266ac7ddfbfSEd Maste             {
267ac7ddfbfSEd Maste                 CommandReturnObject result;
268ac7ddfbfSEd Maste                 Debugger &debugger = target->GetDebugger();
269ac7ddfbfSEd Maste                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
270ac7ddfbfSEd Maste                 // if the debugger is set up that way.
271ac7ddfbfSEd Maste 
272ac7ddfbfSEd Maste                 StreamSP output_stream (debugger.GetAsyncOutputStream());
273ac7ddfbfSEd Maste                 StreamSP error_stream (debugger.GetAsyncErrorStream());
274ac7ddfbfSEd Maste                 result.SetImmediateOutputStream (output_stream);
275ac7ddfbfSEd Maste                 result.SetImmediateErrorStream (error_stream);
276ac7ddfbfSEd Maste 
2777aa51b79SEd Maste                 CommandInterpreterRunOptions options;
2787aa51b79SEd Maste                 options.SetStopOnContinue(true);
2797aa51b79SEd Maste                 options.SetStopOnError (data->stop_on_error);
2807aa51b79SEd Maste                 options.SetEchoCommands (true);
2817aa51b79SEd Maste                 options.SetPrintResults (true);
2827aa51b79SEd Maste                 options.SetAddToHistory (false);
283ac7ddfbfSEd Maste 
284ac7ddfbfSEd Maste                 debugger.GetCommandInterpreter().HandleCommands (commands,
285ac7ddfbfSEd Maste                                                                  &exe_ctx,
2867aa51b79SEd Maste                                                                  options,
287ac7ddfbfSEd Maste                                                                  result);
288ac7ddfbfSEd Maste                 result.GetImmediateOutputStream()->Flush();
289ac7ddfbfSEd Maste                 result.GetImmediateErrorStream()->Flush();
290ac7ddfbfSEd Maste            }
291ac7ddfbfSEd Maste         }
292ac7ddfbfSEd Maste         return ret_value;
293ac7ddfbfSEd Maste     }
294ac7ddfbfSEd Maste 
295ac7ddfbfSEd Maste     class CommandOptions : public Options
296ac7ddfbfSEd Maste     {
297ac7ddfbfSEd Maste     public:
298ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
299ac7ddfbfSEd Maste             Options (interpreter),
300ac7ddfbfSEd Maste             m_use_commands (false),
301ac7ddfbfSEd Maste             m_use_script_language (false),
302ac7ddfbfSEd Maste             m_script_language (eScriptLanguageNone),
303ac7ddfbfSEd Maste             m_use_one_liner (false),
304ac7ddfbfSEd Maste             m_one_liner(),
305ac7ddfbfSEd Maste             m_function_name()
306ac7ddfbfSEd Maste         {
307ac7ddfbfSEd Maste         }
308ac7ddfbfSEd Maste 
3094bb0738eSEd Maste         ~CommandOptions() override = default;
310ac7ddfbfSEd Maste 
3119f2f44ceSEd Maste         Error
3129f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
313ac7ddfbfSEd Maste         {
314ac7ddfbfSEd Maste             Error error;
315ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
316ac7ddfbfSEd Maste 
317ac7ddfbfSEd Maste             switch (short_option)
318ac7ddfbfSEd Maste             {
319ac7ddfbfSEd Maste             case 'o':
320ac7ddfbfSEd Maste                 m_use_one_liner = true;
321ac7ddfbfSEd Maste                 m_one_liner = option_arg;
322ac7ddfbfSEd Maste                 break;
323ac7ddfbfSEd Maste 
324ac7ddfbfSEd Maste             case 's':
325ac7ddfbfSEd Maste                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
326ac7ddfbfSEd Maste                                                                                      g_option_table[option_idx].enum_values,
327ac7ddfbfSEd Maste                                                                                      eScriptLanguageNone,
328ac7ddfbfSEd Maste                                                                                      error);
329ac7ddfbfSEd Maste 
330ac7ddfbfSEd Maste                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
331ac7ddfbfSEd Maste                 {
332ac7ddfbfSEd Maste                     m_use_script_language = true;
333ac7ddfbfSEd Maste                 }
334ac7ddfbfSEd Maste                 else
335ac7ddfbfSEd Maste                 {
336ac7ddfbfSEd Maste                     m_use_script_language = false;
337ac7ddfbfSEd Maste                 }
338ac7ddfbfSEd Maste                 break;
339ac7ddfbfSEd Maste 
340ac7ddfbfSEd Maste             case 'e':
341ac7ddfbfSEd Maste                 {
342ac7ddfbfSEd Maste                     bool success = false;
343ac7ddfbfSEd Maste                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
344ac7ddfbfSEd Maste                     if (!success)
345ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
346ac7ddfbfSEd Maste                 }
347ac7ddfbfSEd Maste                 break;
348ac7ddfbfSEd Maste 
349ac7ddfbfSEd Maste             case 'F':
350ac7ddfbfSEd Maste                 m_use_one_liner = false;
351ac7ddfbfSEd Maste                 m_use_script_language = true;
352ac7ddfbfSEd Maste                 m_function_name.assign(option_arg);
353ac7ddfbfSEd Maste                 break;
354ac7ddfbfSEd Maste 
3557aa51b79SEd Maste             case 'D':
3567aa51b79SEd Maste                 m_use_dummy = true;
3577aa51b79SEd Maste                 break;
3587aa51b79SEd Maste 
359ac7ddfbfSEd Maste             default:
360ac7ddfbfSEd Maste                 break;
361ac7ddfbfSEd Maste             }
362ac7ddfbfSEd Maste             return error;
363ac7ddfbfSEd Maste         }
3644bb0738eSEd Maste 
365ac7ddfbfSEd Maste         void
3669f2f44ceSEd Maste         OptionParsingStarting () override
367ac7ddfbfSEd Maste         {
368ac7ddfbfSEd Maste             m_use_commands = true;
369ac7ddfbfSEd Maste             m_use_script_language = false;
370ac7ddfbfSEd Maste             m_script_language = eScriptLanguageNone;
371ac7ddfbfSEd Maste 
372ac7ddfbfSEd Maste             m_use_one_liner = false;
373ac7ddfbfSEd Maste             m_stop_on_error = true;
374ac7ddfbfSEd Maste             m_one_liner.clear();
375ac7ddfbfSEd Maste             m_function_name.clear();
3767aa51b79SEd Maste             m_use_dummy = false;
377ac7ddfbfSEd Maste         }
378ac7ddfbfSEd Maste 
379ac7ddfbfSEd Maste         const OptionDefinition*
3809f2f44ceSEd Maste         GetDefinitions () override
381ac7ddfbfSEd Maste         {
382ac7ddfbfSEd Maste             return g_option_table;
383ac7ddfbfSEd Maste         }
384ac7ddfbfSEd Maste 
385ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
386ac7ddfbfSEd Maste 
387ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
388ac7ddfbfSEd Maste 
389ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
390ac7ddfbfSEd Maste 
391ac7ddfbfSEd Maste         bool m_use_commands;
392ac7ddfbfSEd Maste         bool m_use_script_language;
393ac7ddfbfSEd Maste         lldb::ScriptLanguage m_script_language;
394ac7ddfbfSEd Maste 
395ac7ddfbfSEd Maste         // Instance variables to hold the values for one_liner options.
396ac7ddfbfSEd Maste         bool m_use_one_liner;
397ac7ddfbfSEd Maste         std::string m_one_liner;
398ac7ddfbfSEd Maste         bool m_stop_on_error;
399ac7ddfbfSEd Maste         std::string m_function_name;
4007aa51b79SEd Maste         bool m_use_dummy;
401ac7ddfbfSEd Maste     };
402ac7ddfbfSEd Maste 
403ac7ddfbfSEd Maste protected:
4049f2f44ceSEd Maste     bool
4059f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
406ac7ddfbfSEd Maste     {
4077aa51b79SEd Maste         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
408ac7ddfbfSEd Maste 
4094bb0738eSEd Maste         if (target == nullptr)
410ac7ddfbfSEd Maste         {
411ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
412ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
413ac7ddfbfSEd Maste             return false;
414ac7ddfbfSEd Maste         }
415ac7ddfbfSEd Maste 
416ac7ddfbfSEd Maste         const BreakpointList &breakpoints = target->GetBreakpointList();
417ac7ddfbfSEd Maste         size_t num_breakpoints = breakpoints.GetSize();
418ac7ddfbfSEd Maste 
419ac7ddfbfSEd Maste         if (num_breakpoints == 0)
420ac7ddfbfSEd Maste         {
421ac7ddfbfSEd Maste             result.AppendError ("No breakpoints exist to have commands added");
422ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
423ac7ddfbfSEd Maste             return false;
424ac7ddfbfSEd Maste         }
425ac7ddfbfSEd Maste 
4264bb0738eSEd Maste         if (!m_options.m_use_script_language && !m_options.m_function_name.empty())
427ac7ddfbfSEd Maste         {
428ac7ddfbfSEd Maste             result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
429ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
430ac7ddfbfSEd Maste             return false;
431ac7ddfbfSEd Maste         }
432ac7ddfbfSEd Maste 
433ac7ddfbfSEd Maste         BreakpointIDList valid_bp_ids;
4347aa51b79SEd Maste         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
435ac7ddfbfSEd Maste 
4360127ef0fSEd Maste         m_bp_options_vec.clear();
4370127ef0fSEd Maste 
438ac7ddfbfSEd Maste         if (result.Succeeded())
439ac7ddfbfSEd Maste         {
440ac7ddfbfSEd Maste             const size_t count = valid_bp_ids.GetSize();
441ac7ddfbfSEd Maste 
442ac7ddfbfSEd Maste             for (size_t i = 0; i < count; ++i)
443ac7ddfbfSEd Maste             {
444ac7ddfbfSEd Maste                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
445ac7ddfbfSEd Maste                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
446ac7ddfbfSEd Maste                 {
447ac7ddfbfSEd Maste                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
4484bb0738eSEd Maste                     BreakpointOptions *bp_options = nullptr;
449ac7ddfbfSEd Maste                     if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
450ac7ddfbfSEd Maste                     {
451ac7ddfbfSEd Maste                         // This breakpoint does not have an associated location.
452ac7ddfbfSEd Maste                         bp_options = bp->GetOptions();
453ac7ddfbfSEd Maste                     }
454ac7ddfbfSEd Maste                     else
455ac7ddfbfSEd Maste                     {
456ac7ddfbfSEd Maste                         BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
457ac7ddfbfSEd Maste                         // This breakpoint does have an associated location.
458ac7ddfbfSEd Maste                         // Get its breakpoint options.
459ac7ddfbfSEd Maste                         if (bp_loc_sp)
460ac7ddfbfSEd Maste                             bp_options = bp_loc_sp->GetLocationOptions();
461ac7ddfbfSEd Maste                     }
4620127ef0fSEd Maste                     if (bp_options)
4630127ef0fSEd Maste                         m_bp_options_vec.push_back (bp_options);
4640127ef0fSEd Maste                 }
4650127ef0fSEd Maste             }
466ac7ddfbfSEd Maste 
467ac7ddfbfSEd Maste             // If we are using script language, get the script interpreter
468ac7ddfbfSEd Maste             // in order to set or collect command callback.  Otherwise, call
469ac7ddfbfSEd Maste             // the methods associated with this object.
470ac7ddfbfSEd Maste             if (m_options.m_use_script_language)
471ac7ddfbfSEd Maste             {
4720127ef0fSEd Maste                 ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
473ac7ddfbfSEd Maste                 // Special handling for one-liner specified inline.
474ac7ddfbfSEd Maste                 if (m_options.m_use_one_liner)
475ac7ddfbfSEd Maste                 {
4760127ef0fSEd Maste                     script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
477ac7ddfbfSEd Maste                                                                  m_options.m_one_liner.c_str());
478ac7ddfbfSEd Maste                 }
4794bb0738eSEd Maste                 else if (!m_options.m_function_name.empty())
480ac7ddfbfSEd Maste                 {
4810127ef0fSEd Maste                     script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
4820127ef0fSEd Maste                                                                          m_options.m_function_name.c_str());
483ac7ddfbfSEd Maste                 }
484ac7ddfbfSEd Maste                 else
485ac7ddfbfSEd Maste                 {
4860127ef0fSEd Maste                     script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
487ac7ddfbfSEd Maste                                                                             result);
488ac7ddfbfSEd Maste                 }
489ac7ddfbfSEd Maste             }
490ac7ddfbfSEd Maste             else
491ac7ddfbfSEd Maste             {
492ac7ddfbfSEd Maste                 // Special handling for one-liner specified inline.
493ac7ddfbfSEd Maste                 if (m_options.m_use_one_liner)
4940127ef0fSEd Maste                     SetBreakpointCommandCallback (m_bp_options_vec,
495ac7ddfbfSEd Maste                                                   m_options.m_one_liner.c_str());
496ac7ddfbfSEd Maste                 else
4970127ef0fSEd Maste                     CollectDataForBreakpointCommandCallback (m_bp_options_vec,
498ac7ddfbfSEd Maste                                                              result);
499ac7ddfbfSEd Maste             }
500ac7ddfbfSEd Maste         }
501ac7ddfbfSEd Maste 
502ac7ddfbfSEd Maste         return result.Succeeded();
503ac7ddfbfSEd Maste     }
504ac7ddfbfSEd Maste 
505ac7ddfbfSEd Maste private:
506ac7ddfbfSEd Maste     CommandOptions m_options;
5070127ef0fSEd Maste     std::vector<BreakpointOptions *> m_bp_options_vec;  // This stores the breakpoint options that we are currently
5080127ef0fSEd Maste                                                         // collecting commands for.  In the CollectData... calls we need
5090127ef0fSEd Maste                                                         // to hand this off to the IOHandler, which may run asynchronously.
5100127ef0fSEd Maste                                                         // So we have to have some way to keep it alive, and not leak it.
5110127ef0fSEd Maste                                                         // Making it an ivar of the command object, which never goes away
5120127ef0fSEd Maste                                                         // achieves this.  Note that if we were able to run
5130127ef0fSEd Maste                                                         // the same command concurrently in one interpreter we'd have to
5140127ef0fSEd Maste                                                         // make this "per invocation".  But there are many more reasons
5150127ef0fSEd Maste                                                         // why it is not in general safe to do that in lldb at present,
5160127ef0fSEd Maste                                                         // so it isn't worthwhile to come up with a more complex mechanism
5170127ef0fSEd Maste                                                         // to address this particular weakness right now.
518ac7ddfbfSEd Maste     static const char *g_reader_instructions;
519ac7ddfbfSEd Maste };
520ac7ddfbfSEd Maste 
521ac7ddfbfSEd Maste const char *
52212b93ac6SEd Maste CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.\n";
523ac7ddfbfSEd Maste 
524ac7ddfbfSEd Maste // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
525ac7ddfbfSEd Maste // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
526ac7ddfbfSEd Maste 
527ac7ddfbfSEd Maste static OptionEnumValueElement
528ac7ddfbfSEd Maste g_script_option_enumeration[4] =
529ac7ddfbfSEd Maste {
530ac7ddfbfSEd Maste     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
531ac7ddfbfSEd Maste     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
532ac7ddfbfSEd Maste     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
5334bb0738eSEd Maste     { 0,                      nullptr,           nullptr }
534ac7ddfbfSEd Maste };
535ac7ddfbfSEd Maste 
536ac7ddfbfSEd Maste OptionDefinition
537ac7ddfbfSEd Maste CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
538ac7ddfbfSEd Maste {
5394bb0738eSEd Maste     { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner,
540ac7ddfbfSEd Maste         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
541ac7ddfbfSEd Maste 
5424bb0738eSEd Maste     { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
543ac7ddfbfSEd Maste         "Specify whether breakpoint command execution should terminate on error." },
544ac7ddfbfSEd Maste 
5454bb0738eSEd Maste     { LLDB_OPT_SET_ALL,   false, "script-type",     's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone,
546ac7ddfbfSEd Maste         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
547ac7ddfbfSEd Maste 
5484bb0738eSEd Maste     { LLDB_OPT_SET_2,   false, "python-function",     'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction,
549ac7ddfbfSEd Maste         "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
550ac7ddfbfSEd Maste 
5514bb0738eSEd Maste     { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
5527aa51b79SEd Maste         "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
5537aa51b79SEd Maste 
5544bb0738eSEd Maste     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
555ac7ddfbfSEd Maste };
556ac7ddfbfSEd Maste 
557ac7ddfbfSEd Maste //-------------------------------------------------------------------------
558ac7ddfbfSEd Maste // CommandObjectBreakpointCommandDelete
559ac7ddfbfSEd Maste //-------------------------------------------------------------------------
560ac7ddfbfSEd Maste 
561ac7ddfbfSEd Maste class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
562ac7ddfbfSEd Maste {
563ac7ddfbfSEd Maste public:
564ac7ddfbfSEd Maste     CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
565ac7ddfbfSEd Maste         CommandObjectParsed(interpreter,
566ac7ddfbfSEd Maste                             "delete",
567ac7ddfbfSEd Maste                             "Delete the set of commands from a breakpoint.",
5684bb0738eSEd Maste                             nullptr),
5697aa51b79SEd Maste         m_options (interpreter)
570ac7ddfbfSEd Maste     {
571ac7ddfbfSEd Maste         CommandArgumentEntry arg;
572ac7ddfbfSEd Maste         CommandArgumentData bp_id_arg;
573ac7ddfbfSEd Maste 
574ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
575ac7ddfbfSEd Maste         bp_id_arg.arg_type = eArgTypeBreakpointID;
576ac7ddfbfSEd Maste         bp_id_arg.arg_repetition = eArgRepeatPlain;
577ac7ddfbfSEd Maste 
578ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
579ac7ddfbfSEd Maste         arg.push_back (bp_id_arg);
580ac7ddfbfSEd Maste 
581ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
582ac7ddfbfSEd Maste         m_arguments.push_back (arg);
583ac7ddfbfSEd Maste     }
584ac7ddfbfSEd Maste 
5854bb0738eSEd Maste     ~CommandObjectBreakpointCommandDelete() override = default;
586ac7ddfbfSEd Maste 
5879f2f44ceSEd Maste     Options *
5889f2f44ceSEd Maste     GetOptions () override
5897aa51b79SEd Maste     {
5907aa51b79SEd Maste         return &m_options;
5917aa51b79SEd Maste     }
5927aa51b79SEd Maste 
5937aa51b79SEd Maste     class CommandOptions : public Options
5947aa51b79SEd Maste     {
5957aa51b79SEd Maste     public:
5967aa51b79SEd Maste         CommandOptions (CommandInterpreter &interpreter) :
5977aa51b79SEd Maste             Options (interpreter),
5987aa51b79SEd Maste             m_use_dummy (false)
5997aa51b79SEd Maste         {
6007aa51b79SEd Maste         }
6017aa51b79SEd Maste 
6024bb0738eSEd Maste         ~CommandOptions() override = default;
6037aa51b79SEd Maste 
6049f2f44ceSEd Maste         Error
6059f2f44ceSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg) override
6067aa51b79SEd Maste         {
6077aa51b79SEd Maste             Error error;
6087aa51b79SEd Maste             const int short_option = m_getopt_table[option_idx].val;
6097aa51b79SEd Maste 
6107aa51b79SEd Maste             switch (short_option)
6117aa51b79SEd Maste             {
6127aa51b79SEd Maste                 case 'D':
6137aa51b79SEd Maste                     m_use_dummy = true;
6147aa51b79SEd Maste                     break;
6157aa51b79SEd Maste 
6167aa51b79SEd Maste                 default:
6177aa51b79SEd Maste                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
6187aa51b79SEd Maste                     break;
6197aa51b79SEd Maste             }
6207aa51b79SEd Maste 
6217aa51b79SEd Maste             return error;
6227aa51b79SEd Maste         }
6237aa51b79SEd Maste 
6247aa51b79SEd Maste         void
6259f2f44ceSEd Maste         OptionParsingStarting () override
6267aa51b79SEd Maste         {
6277aa51b79SEd Maste             m_use_dummy = false;
6287aa51b79SEd Maste         }
6297aa51b79SEd Maste 
6307aa51b79SEd Maste         const OptionDefinition*
6319f2f44ceSEd Maste         GetDefinitions () override
6327aa51b79SEd Maste         {
6337aa51b79SEd Maste             return g_option_table;
6347aa51b79SEd Maste         }
6357aa51b79SEd Maste 
6367aa51b79SEd Maste         // Options table: Required for subclasses of Options.
6377aa51b79SEd Maste 
6387aa51b79SEd Maste         static OptionDefinition g_option_table[];
6397aa51b79SEd Maste 
6407aa51b79SEd Maste         // Instance variables to hold the values for command options.
6417aa51b79SEd Maste         bool m_use_dummy;
6427aa51b79SEd Maste     };
6437aa51b79SEd Maste 
644ac7ddfbfSEd Maste protected:
6459f2f44ceSEd Maste     bool
6469f2f44ceSEd Maste     DoExecute (Args& command, CommandReturnObject &result) override
647ac7ddfbfSEd Maste     {
6487aa51b79SEd Maste         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
649ac7ddfbfSEd Maste 
6504bb0738eSEd Maste         if (target == nullptr)
651ac7ddfbfSEd Maste         {
652ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
653ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
654ac7ddfbfSEd Maste             return false;
655ac7ddfbfSEd Maste         }
656ac7ddfbfSEd Maste 
657ac7ddfbfSEd Maste         const BreakpointList &breakpoints = target->GetBreakpointList();
658ac7ddfbfSEd Maste         size_t num_breakpoints = breakpoints.GetSize();
659ac7ddfbfSEd Maste 
660ac7ddfbfSEd Maste         if (num_breakpoints == 0)
661ac7ddfbfSEd Maste         {
662ac7ddfbfSEd Maste             result.AppendError ("No breakpoints exist to have commands deleted");
663ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
664ac7ddfbfSEd Maste             return false;
665ac7ddfbfSEd Maste         }
666ac7ddfbfSEd Maste 
667ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
668ac7ddfbfSEd Maste         {
669ac7ddfbfSEd Maste             result.AppendError ("No breakpoint specified from which to delete the commands");
670ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
671ac7ddfbfSEd Maste             return false;
672ac7ddfbfSEd Maste         }
673ac7ddfbfSEd Maste 
674ac7ddfbfSEd Maste         BreakpointIDList valid_bp_ids;
6757aa51b79SEd Maste         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
676ac7ddfbfSEd Maste 
677ac7ddfbfSEd Maste         if (result.Succeeded())
678ac7ddfbfSEd Maste         {
679ac7ddfbfSEd Maste             const size_t count = valid_bp_ids.GetSize();
680ac7ddfbfSEd Maste             for (size_t i = 0; i < count; ++i)
681ac7ddfbfSEd Maste             {
682ac7ddfbfSEd Maste                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
683ac7ddfbfSEd Maste                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
684ac7ddfbfSEd Maste                 {
685ac7ddfbfSEd Maste                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
686ac7ddfbfSEd Maste                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
687ac7ddfbfSEd Maste                     {
688ac7ddfbfSEd Maste                         BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
689ac7ddfbfSEd Maste                         if (bp_loc_sp)
690ac7ddfbfSEd Maste                             bp_loc_sp->ClearCallback();
691ac7ddfbfSEd Maste                         else
692ac7ddfbfSEd Maste                         {
693ac7ddfbfSEd Maste                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
694ac7ddfbfSEd Maste                                                          cur_bp_id.GetBreakpointID(),
695ac7ddfbfSEd Maste                                                          cur_bp_id.GetLocationID());
696ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
697ac7ddfbfSEd Maste                             return false;
698ac7ddfbfSEd Maste                         }
699ac7ddfbfSEd Maste                     }
700ac7ddfbfSEd Maste                     else
701ac7ddfbfSEd Maste                     {
702ac7ddfbfSEd Maste                         bp->ClearCallback();
703ac7ddfbfSEd Maste                     }
704ac7ddfbfSEd Maste                 }
705ac7ddfbfSEd Maste             }
706ac7ddfbfSEd Maste         }
707ac7ddfbfSEd Maste         return result.Succeeded();
708ac7ddfbfSEd Maste     }
7094bb0738eSEd Maste 
7107aa51b79SEd Maste private:
7117aa51b79SEd Maste     CommandOptions m_options;
712ac7ddfbfSEd Maste };
713ac7ddfbfSEd Maste 
7147aa51b79SEd Maste OptionDefinition
7157aa51b79SEd Maste CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
7167aa51b79SEd Maste {
7174bb0738eSEd Maste     { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
7187aa51b79SEd Maste         "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
7197aa51b79SEd Maste 
7204bb0738eSEd Maste     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
7217aa51b79SEd Maste };
7227aa51b79SEd Maste 
723ac7ddfbfSEd Maste //-------------------------------------------------------------------------
724ac7ddfbfSEd Maste // CommandObjectBreakpointCommandList
725ac7ddfbfSEd Maste //-------------------------------------------------------------------------
726ac7ddfbfSEd Maste 
727ac7ddfbfSEd Maste class CommandObjectBreakpointCommandList : public CommandObjectParsed
728ac7ddfbfSEd Maste {
729ac7ddfbfSEd Maste public:
730ac7ddfbfSEd Maste     CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
731ac7ddfbfSEd Maste         CommandObjectParsed(interpreter,
732ac7ddfbfSEd Maste                             "list",
733ac7ddfbfSEd Maste                             "List the script or set of commands to be executed when the breakpoint is hit.",
7344bb0738eSEd Maste                             nullptr)
735ac7ddfbfSEd Maste     {
736ac7ddfbfSEd Maste         CommandArgumentEntry arg;
737ac7ddfbfSEd Maste         CommandArgumentData bp_id_arg;
738ac7ddfbfSEd Maste 
739ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
740ac7ddfbfSEd Maste         bp_id_arg.arg_type = eArgTypeBreakpointID;
741ac7ddfbfSEd Maste         bp_id_arg.arg_repetition = eArgRepeatPlain;
742ac7ddfbfSEd Maste 
743ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
744ac7ddfbfSEd Maste         arg.push_back (bp_id_arg);
745ac7ddfbfSEd Maste 
746ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
747ac7ddfbfSEd Maste         m_arguments.push_back (arg);
748ac7ddfbfSEd Maste     }
749ac7ddfbfSEd Maste 
7504bb0738eSEd Maste     ~CommandObjectBreakpointCommandList() override = default;
751ac7ddfbfSEd Maste 
752ac7ddfbfSEd Maste protected:
7539f2f44ceSEd Maste     bool
754ac7ddfbfSEd Maste     DoExecute (Args& command,
7559f2f44ceSEd Maste              CommandReturnObject &result) override
756ac7ddfbfSEd Maste     {
757ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
758ac7ddfbfSEd Maste 
7594bb0738eSEd Maste         if (target == nullptr)
760ac7ddfbfSEd Maste         {
761ac7ddfbfSEd Maste             result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
762ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
763ac7ddfbfSEd Maste             return false;
764ac7ddfbfSEd Maste         }
765ac7ddfbfSEd Maste 
766ac7ddfbfSEd Maste         const BreakpointList &breakpoints = target->GetBreakpointList();
767ac7ddfbfSEd Maste         size_t num_breakpoints = breakpoints.GetSize();
768ac7ddfbfSEd Maste 
769ac7ddfbfSEd Maste         if (num_breakpoints == 0)
770ac7ddfbfSEd Maste         {
771ac7ddfbfSEd Maste             result.AppendError ("No breakpoints exist for which to list commands");
772ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
773ac7ddfbfSEd Maste             return false;
774ac7ddfbfSEd Maste         }
775ac7ddfbfSEd Maste 
776ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
777ac7ddfbfSEd Maste         {
778ac7ddfbfSEd Maste             result.AppendError ("No breakpoint specified for which to list the commands");
779ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
780ac7ddfbfSEd Maste             return false;
781ac7ddfbfSEd Maste         }
782ac7ddfbfSEd Maste 
783ac7ddfbfSEd Maste         BreakpointIDList valid_bp_ids;
7847aa51b79SEd Maste         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
785ac7ddfbfSEd Maste 
786ac7ddfbfSEd Maste         if (result.Succeeded())
787ac7ddfbfSEd Maste         {
788ac7ddfbfSEd Maste             const size_t count = valid_bp_ids.GetSize();
789ac7ddfbfSEd Maste             for (size_t i = 0; i < count; ++i)
790ac7ddfbfSEd Maste             {
791ac7ddfbfSEd Maste                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
792ac7ddfbfSEd Maste                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
793ac7ddfbfSEd Maste                 {
794ac7ddfbfSEd Maste                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
795ac7ddfbfSEd Maste 
796ac7ddfbfSEd Maste                     if (bp)
797ac7ddfbfSEd Maste                     {
7984bb0738eSEd Maste                         const BreakpointOptions *bp_options = nullptr;
799ac7ddfbfSEd Maste                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
800ac7ddfbfSEd Maste                         {
801ac7ddfbfSEd Maste                             BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
802ac7ddfbfSEd Maste                             if (bp_loc_sp)
803ac7ddfbfSEd Maste                                 bp_options = bp_loc_sp->GetOptionsNoCreate();
804ac7ddfbfSEd Maste                             else
805ac7ddfbfSEd Maste                             {
806ac7ddfbfSEd Maste                                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
807ac7ddfbfSEd Maste                                                              cur_bp_id.GetBreakpointID(),
808ac7ddfbfSEd Maste                                                              cur_bp_id.GetLocationID());
809ac7ddfbfSEd Maste                                 result.SetStatus (eReturnStatusFailed);
810ac7ddfbfSEd Maste                                 return false;
811ac7ddfbfSEd Maste                             }
812ac7ddfbfSEd Maste                         }
813ac7ddfbfSEd Maste                         else
814ac7ddfbfSEd Maste                         {
815ac7ddfbfSEd Maste                             bp_options = bp->GetOptions();
816ac7ddfbfSEd Maste                         }
817ac7ddfbfSEd Maste 
818ac7ddfbfSEd Maste                         if (bp_options)
819ac7ddfbfSEd Maste                         {
820ac7ddfbfSEd Maste                             StreamString id_str;
821ac7ddfbfSEd Maste                             BreakpointID::GetCanonicalReference (&id_str,
822ac7ddfbfSEd Maste                                                                  cur_bp_id.GetBreakpointID(),
823ac7ddfbfSEd Maste                                                                  cur_bp_id.GetLocationID());
824ac7ddfbfSEd Maste                             const Baton *baton = bp_options->GetBaton();
825ac7ddfbfSEd Maste                             if (baton)
826ac7ddfbfSEd Maste                             {
827ac7ddfbfSEd Maste                                 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
828ac7ddfbfSEd Maste                                 result.GetOutputStream().IndentMore ();
829ac7ddfbfSEd Maste                                 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
830ac7ddfbfSEd Maste                                 result.GetOutputStream().IndentLess ();
831ac7ddfbfSEd Maste                             }
832ac7ddfbfSEd Maste                             else
833ac7ddfbfSEd Maste                             {
834ac7ddfbfSEd Maste                                 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
835ac7ddfbfSEd Maste                                                                 id_str.GetData());
836ac7ddfbfSEd Maste                             }
837ac7ddfbfSEd Maste                         }
838ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusSuccessFinishResult);
839ac7ddfbfSEd Maste                     }
840ac7ddfbfSEd Maste                     else
841ac7ddfbfSEd Maste                     {
842ac7ddfbfSEd Maste                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
843ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
844ac7ddfbfSEd Maste                     }
845ac7ddfbfSEd Maste                 }
846ac7ddfbfSEd Maste             }
847ac7ddfbfSEd Maste         }
848ac7ddfbfSEd Maste 
849ac7ddfbfSEd Maste         return result.Succeeded();
850ac7ddfbfSEd Maste     }
851ac7ddfbfSEd Maste };
852ac7ddfbfSEd Maste 
853ac7ddfbfSEd Maste //-------------------------------------------------------------------------
854ac7ddfbfSEd Maste // CommandObjectBreakpointCommand
855ac7ddfbfSEd Maste //-------------------------------------------------------------------------
856ac7ddfbfSEd Maste 
8574bb0738eSEd Maste CommandObjectBreakpointCommand::CommandObjectBreakpointCommand(CommandInterpreter &interpreter)
8584bb0738eSEd Maste     : CommandObjectMultiword(
8594bb0738eSEd Maste           interpreter, "command",
8604bb0738eSEd Maste           "Commands for adding, removing and listing LLDB commands executed when a breakpoint is hit.",
861ac7ddfbfSEd Maste           "command <sub-command> [<sub-command-options>] <breakpoint-id>")
862ac7ddfbfSEd Maste {
863ac7ddfbfSEd Maste     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
864ac7ddfbfSEd Maste     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
865ac7ddfbfSEd Maste     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
866ac7ddfbfSEd Maste 
867ac7ddfbfSEd Maste     add_command_object->SetCommandName ("breakpoint command add");
868ac7ddfbfSEd Maste     delete_command_object->SetCommandName ("breakpoint command delete");
869ac7ddfbfSEd Maste     list_command_object->SetCommandName ("breakpoint command list");
870ac7ddfbfSEd Maste 
871ac7ddfbfSEd Maste     LoadSubCommand ("add",    add_command_object);
872ac7ddfbfSEd Maste     LoadSubCommand ("delete", delete_command_object);
873ac7ddfbfSEd Maste     LoadSubCommand ("list",   list_command_object);
874ac7ddfbfSEd Maste }
875ac7ddfbfSEd Maste 
8764bb0738eSEd Maste CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand() = default;
877