130fdc8d8SChris Lattner //===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner // C Includes
1130fdc8d8SChris Lattner // C++ Includes
12c8ecc2a9SEugene Zelenko // Other libraries and framework includes
13c8ecc2a9SEugene Zelenko // Project includes
1430fdc8d8SChris Lattner #include "CommandObjectBreakpointCommand.h"
1530fdc8d8SChris Lattner #include "CommandObjectBreakpoint.h"
1644d93782SGreg Clayton #include "lldb/Core/IOHandler.h"
1730fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
1830fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
1930fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2030fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2130fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointIDList.h"
2230fdc8d8SChris Lattner #include "lldb/Breakpoint/Breakpoint.h"
2330fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h"
2430fdc8d8SChris Lattner #include "lldb/Breakpoint/StoppointCallbackContext.h"
2530fdc8d8SChris Lattner #include "lldb/Core/State.h"
2630fdc8d8SChris Lattner 
2730fdc8d8SChris Lattner using namespace lldb;
2830fdc8d8SChris Lattner using namespace lldb_private;
2930fdc8d8SChris Lattner 
3030fdc8d8SChris Lattner //-------------------------------------------------------------------------
3130fdc8d8SChris Lattner // CommandObjectBreakpointCommandAdd
3230fdc8d8SChris Lattner //-------------------------------------------------------------------------
3330fdc8d8SChris Lattner 
3444d93782SGreg Clayton class CommandObjectBreakpointCommandAdd :
3544d93782SGreg Clayton     public CommandObjectParsed,
3644d93782SGreg Clayton     public IOHandlerDelegateMultiline
375a988416SJim Ingham {
385a988416SJim Ingham public:
397428a18cSKate Stone     CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter)
407428a18cSKate Stone         : CommandObjectParsed(interpreter, "add",
417428a18cSKate Stone                               "Add LLDB commands to a breakpoint, to be executed whenever the breakpoint is hit."
421bb0750bSJim Ingham                               "  If no breakpoint is specified, adds the commands to the last created breakpoint.",
43c8ecc2a9SEugene Zelenko                               nullptr),
44c3d874a5SGreg Clayton           IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand),
45e1cfbc79STodd Fiala           m_options()
4630fdc8d8SChris Lattner     {
4730fdc8d8SChris Lattner         SetHelpLong (
48ea671fbdSKate Stone R"(
49ea671fbdSKate Stone General information about entering breakpoint commands
50ea671fbdSKate Stone ------------------------------------------------------
51ea671fbdSKate Stone 
52ea671fbdSKate Stone )" "This command will prompt for commands to be executed when the specified \
53ea671fbdSKate Stone breakpoint is hit.  Each command is typed on its own line following the '> ' \
54ea671fbdSKate Stone prompt until 'DONE' is entered." R"(
55ea671fbdSKate Stone 
56ea671fbdSKate Stone )" "Syntactic errors may not be detected when initially entered, and many \
57ea671fbdSKate Stone malformed commands can silently fail when executed.  If your breakpoint commands \
58ea671fbdSKate Stone do not appear to be executing, double-check the command syntax." R"(
59ea671fbdSKate Stone 
60ea671fbdSKate Stone )" "Note: You may enter any debugger command exactly as you would at the debugger \
61ea671fbdSKate Stone prompt.  There is no limit to the number of commands supplied, but do NOT enter \
62ea671fbdSKate Stone more than one command per line." R"(
63ea671fbdSKate Stone 
64ea671fbdSKate Stone Special information about PYTHON breakpoint commands
65ea671fbdSKate Stone ----------------------------------------------------
66ea671fbdSKate Stone 
67ea671fbdSKate Stone )" "You may enter either one or more lines of Python, including function \
68ea671fbdSKate Stone definitions or calls to functions that will have been imported by the time \
69ea671fbdSKate Stone the code executes.  Single line breakpoint commands will be interpreted 'as is' \
70ea671fbdSKate Stone when the breakpoint is hit.  Multiple lines of Python will be wrapped in a \
71ea671fbdSKate Stone generated function, and a call to the function will be attached to the breakpoint." R"(
72ea671fbdSKate Stone 
73ea671fbdSKate Stone This auto-generated function is passed in three arguments:
74ea671fbdSKate Stone 
75ea671fbdSKate Stone     frame:  an lldb.SBFrame object for the frame which hit breakpoint.
76ea671fbdSKate Stone 
77ea671fbdSKate Stone     bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
78ea671fbdSKate Stone 
79ea671fbdSKate Stone     dict:   the python session dictionary hit.
80ea671fbdSKate Stone 
81ea671fbdSKate Stone )" "When specifying a python function with the --python-function option, you need \
82ea671fbdSKate Stone to supply the function name prepended by the module name:" R"(
83ea671fbdSKate Stone 
84ea671fbdSKate Stone     --python-function myutils.breakpoint_callback
85ea671fbdSKate Stone 
86ea671fbdSKate Stone The function itself must have the following prototype:
87ea671fbdSKate Stone 
88ea671fbdSKate Stone def breakpoint_callback(frame, bp_loc, dict):
89ea671fbdSKate Stone   # Your code goes here
90ea671fbdSKate Stone 
91ea671fbdSKate Stone )" "The arguments are the same as the arguments passed to generated functions as \
92ea671fbdSKate Stone described above.  Note that the global variable 'lldb.frame' will NOT be updated when \
93ea671fbdSKate Stone this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
94ea671fbdSKate Stone can get you to the thread via frame.GetThread(), the thread can get you to the \
95ea671fbdSKate Stone process via thread.GetProcess(), and the process can get you back to the target \
96ea671fbdSKate Stone via process.GetTarget()." R"(
97ea671fbdSKate Stone 
98ea671fbdSKate Stone )" "Important Note: As Python code gets collected into functions, access to global \
99ea671fbdSKate Stone variables requires explicit scoping using the 'global' keyword.  Be sure to use correct \
100ea671fbdSKate Stone Python syntax, including indentation, when entering Python breakpoint commands." R"(
101ea671fbdSKate Stone 
102ea671fbdSKate Stone Example Python one-line breakpoint command:
103ea671fbdSKate Stone 
104ea671fbdSKate Stone (lldb) breakpoint command add -s python 1
105ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
106ea671fbdSKate Stone > print "Hit this breakpoint!"
107ea671fbdSKate Stone > DONE
108ea671fbdSKate Stone 
109ea671fbdSKate Stone As a convenience, this also works for a short Python one-liner:
110ea671fbdSKate Stone 
111ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
112ea671fbdSKate Stone (lldb) run
113ea671fbdSKate Stone Launching '.../a.out'  (x86_64)
114ea671fbdSKate Stone (lldb) Fri Sep 10 12:17:45 2010
115ea671fbdSKate Stone Process 21778 Stopped
116ea671fbdSKate Stone * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
117ea671fbdSKate Stone   36
118ea671fbdSKate Stone   37   	int c(int val)
119ea671fbdSKate Stone   38   	{
120ea671fbdSKate Stone   39 ->	    return val + 3;
121ea671fbdSKate Stone   40   	}
122ea671fbdSKate Stone   41
123ea671fbdSKate Stone   42   	int main (int argc, char const *argv[])
124ea671fbdSKate Stone 
125ea671fbdSKate Stone Example multiple line Python breakpoint command:
126ea671fbdSKate Stone 
127ea671fbdSKate Stone (lldb) breakpoint command add -s p 1
128ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
129ea671fbdSKate Stone > global bp_count
130ea671fbdSKate Stone > bp_count = bp_count + 1
131ea671fbdSKate Stone > print "Hit this breakpoint " + repr(bp_count) + " times!"
132ea671fbdSKate Stone > DONE
133ea671fbdSKate Stone 
134ea671fbdSKate Stone Example multiple line Python breakpoint command, using function definition:
135ea671fbdSKate Stone 
136ea671fbdSKate Stone (lldb) breakpoint command add -s python 1
137ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
138ea671fbdSKate Stone > def breakpoint_output (bp_no):
139ea671fbdSKate Stone >     out_string = "Hit breakpoint number " + repr (bp_no)
140ea671fbdSKate Stone >     print out_string
141ea671fbdSKate Stone >     return True
142ea671fbdSKate Stone > breakpoint_output (1)
143ea671fbdSKate Stone > DONE
144ea671fbdSKate Stone 
145ea671fbdSKate Stone )" "In this case, since there is a reference to a global variable, \
146ea671fbdSKate Stone 'bp_count', you will also need to make sure 'bp_count' exists and is \
147ea671fbdSKate Stone initialized:" R"(
148ea671fbdSKate Stone 
149ea671fbdSKate Stone (lldb) script
150ea671fbdSKate Stone >>> bp_count = 0
151ea671fbdSKate Stone >>> quit()
152ea671fbdSKate Stone 
153ea671fbdSKate Stone )" "Your Python code, however organized, can optionally return a value.  \
154ea671fbdSKate Stone If the returned value is False, that tells LLDB not to stop at the breakpoint \
155ea671fbdSKate Stone to which the code is associated. Returning anything other than False, or even \
156ea671fbdSKate Stone returning None, or even omitting a return statement entirely, will cause \
157ea671fbdSKate Stone LLDB to stop." R"(
158ea671fbdSKate Stone 
159ea671fbdSKate Stone )" "Final Note: A warning that no breakpoint command was generated when there \
160ea671fbdSKate Stone are no syntax errors may indicate that a function was declared but never called."
161ea671fbdSKate Stone         );
162405fe67fSCaroline Tice 
163405fe67fSCaroline Tice         CommandArgumentEntry arg;
164405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
165405fe67fSCaroline Tice 
166405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
167405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
1681bb0750bSJim Ingham         bp_id_arg.arg_repetition = eArgRepeatOptional;
169405fe67fSCaroline Tice 
170405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
171405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
172405fe67fSCaroline Tice 
173405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
174405fe67fSCaroline Tice         m_arguments.push_back (arg);
17530fdc8d8SChris Lattner     }
17630fdc8d8SChris Lattner 
177c8ecc2a9SEugene Zelenko     ~CommandObjectBreakpointCommandAdd() override = default;
1785a988416SJim Ingham 
17913d21e9aSBruce Mitchener     Options *
18013d21e9aSBruce Mitchener     GetOptions () override
1815a988416SJim Ingham     {
1825a988416SJim Ingham         return &m_options;
1835a988416SJim Ingham     }
1845a988416SJim Ingham 
18513d21e9aSBruce Mitchener     void
18613d21e9aSBruce Mitchener     IOHandlerActivated (IOHandler &io_handler) override
18744d93782SGreg Clayton     {
18844d93782SGreg Clayton         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
18944d93782SGreg Clayton         if (output_sp)
19044d93782SGreg Clayton         {
19144d93782SGreg Clayton             output_sp->PutCString(g_reader_instructions);
19244d93782SGreg Clayton             output_sp->Flush();
19344d93782SGreg Clayton         }
19444d93782SGreg Clayton     }
19544d93782SGreg Clayton 
19613d21e9aSBruce Mitchener     void
19713d21e9aSBruce Mitchener     IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override
19844d93782SGreg Clayton     {
19944d93782SGreg Clayton         io_handler.SetIsDone(true);
20044d93782SGreg Clayton 
201b5796cb4SJim Ingham         std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
202b5796cb4SJim Ingham         for (BreakpointOptions *bp_options : *bp_options_vec)
20344d93782SGreg Clayton         {
204b5796cb4SJim Ingham             if (!bp_options)
205b5796cb4SJim Ingham                 continue;
206b5796cb4SJim Ingham 
20744d93782SGreg Clayton             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
208c8ecc2a9SEugene Zelenko             if (data_ap)
20944d93782SGreg Clayton             {
21044d93782SGreg Clayton                 data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
21144d93782SGreg Clayton                 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
21244d93782SGreg Clayton                 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
21344d93782SGreg Clayton             }
21444d93782SGreg Clayton         }
21544d93782SGreg Clayton     }
21644d93782SGreg Clayton 
2175a988416SJim Ingham     void
218b5796cb4SJim Ingham     CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
2195a988416SJim Ingham                                              CommandReturnObject &result)
2205a988416SJim Ingham     {
22144d93782SGreg Clayton         m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
22244d93782SGreg Clayton                                                     *this,          // IOHandlerDelegate
22344d93782SGreg Clayton                                                     true,           // Run IOHandler in async mode
224b5796cb4SJim Ingham                                                     &bp_options_vec);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
2255a988416SJim Ingham     }
2265a988416SJim Ingham 
2275a988416SJim Ingham     /// Set a one-liner as the callback for the breakpoint.
2285a988416SJim Ingham     void
229b5796cb4SJim Ingham     SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
2305a988416SJim Ingham                                   const char *oneliner)
2315a988416SJim Ingham     {
232b5796cb4SJim Ingham         for (auto bp_options : bp_options_vec)
233b5796cb4SJim Ingham         {
2347b0992d9SGreg Clayton             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
2355a988416SJim Ingham 
2365a988416SJim Ingham             // It's necessary to set both user_source and script_source to the oneliner.
2375a988416SJim Ingham             // The former is used to generate callback description (as in breakpoint command list)
2385a988416SJim Ingham             // while the latter is used for Python to interpret during the actual callback.
2395a988416SJim Ingham             data_ap->user_source.AppendString (oneliner);
2405a988416SJim Ingham             data_ap->script_source.assign (oneliner);
2415a988416SJim Ingham             data_ap->stop_on_error = m_options.m_stop_on_error;
2425a988416SJim Ingham 
2435a988416SJim Ingham             BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
2445a988416SJim Ingham             bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
245b5796cb4SJim Ingham         }
2465a988416SJim Ingham     }
2475a988416SJim Ingham 
2485a988416SJim Ingham     static bool
2495a988416SJim Ingham     BreakpointOptionsCallbackFunction (void *baton,
2505a988416SJim Ingham                                        StoppointCallbackContext *context,
2515a988416SJim Ingham                                        lldb::user_id_t break_id,
2525a988416SJim Ingham                                        lldb::user_id_t break_loc_id)
2535a988416SJim Ingham     {
2545a988416SJim Ingham         bool ret_value = true;
255c8ecc2a9SEugene Zelenko         if (baton == nullptr)
2565a988416SJim Ingham             return true;
2575a988416SJim Ingham 
2585a988416SJim Ingham         BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
2595a988416SJim Ingham         StringList &commands = data->user_source;
2605a988416SJim Ingham 
2615a988416SJim Ingham         if (commands.GetSize() > 0)
2625a988416SJim Ingham         {
2635a988416SJim Ingham             ExecutionContext exe_ctx (context->exe_ctx_ref);
2645a988416SJim Ingham             Target *target = exe_ctx.GetTargetPtr();
2655a988416SJim Ingham             if (target)
2665a988416SJim Ingham             {
2675a988416SJim Ingham                 CommandReturnObject result;
2685a988416SJim Ingham                 Debugger &debugger = target->GetDebugger();
2695a988416SJim Ingham                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
2705a988416SJim Ingham                 // if the debugger is set up that way.
2715a988416SJim Ingham 
2725a988416SJim Ingham                 StreamSP output_stream (debugger.GetAsyncOutputStream());
2735a988416SJim Ingham                 StreamSP error_stream (debugger.GetAsyncErrorStream());
2745a988416SJim Ingham                 result.SetImmediateOutputStream (output_stream);
2755a988416SJim Ingham                 result.SetImmediateErrorStream (error_stream);
2765a988416SJim Ingham 
27726c7bf93SJim Ingham                 CommandInterpreterRunOptions options;
27826c7bf93SJim Ingham                 options.SetStopOnContinue(true);
27926c7bf93SJim Ingham                 options.SetStopOnError (data->stop_on_error);
28026c7bf93SJim Ingham                 options.SetEchoCommands (true);
28126c7bf93SJim Ingham                 options.SetPrintResults (true);
28226c7bf93SJim Ingham                 options.SetAddToHistory (false);
2835a988416SJim Ingham 
2845a988416SJim Ingham                 debugger.GetCommandInterpreter().HandleCommands (commands,
2855a988416SJim Ingham                                                                  &exe_ctx,
28626c7bf93SJim Ingham                                                                  options,
2875a988416SJim Ingham                                                                  result);
2885a988416SJim Ingham                 result.GetImmediateOutputStream()->Flush();
2895a988416SJim Ingham                 result.GetImmediateErrorStream()->Flush();
2905a988416SJim Ingham            }
2915a988416SJim Ingham         }
2925a988416SJim Ingham         return ret_value;
2935a988416SJim Ingham     }
2945a988416SJim Ingham 
2955a988416SJim Ingham     class CommandOptions : public Options
2965a988416SJim Ingham     {
2975a988416SJim Ingham     public:
298e1cfbc79STodd Fiala         CommandOptions () :
299e1cfbc79STodd Fiala             Options (),
3005a988416SJim Ingham             m_use_commands (false),
3015a988416SJim Ingham             m_use_script_language (false),
3025a988416SJim Ingham             m_script_language (eScriptLanguageNone),
3035a988416SJim Ingham             m_use_one_liner (false),
3045a988416SJim Ingham             m_one_liner(),
3055a988416SJim Ingham             m_function_name()
30630fdc8d8SChris Lattner         {
30730fdc8d8SChris Lattner         }
30830fdc8d8SChris Lattner 
309c8ecc2a9SEugene Zelenko         ~CommandOptions() override = default;
3105a988416SJim Ingham 
31113d21e9aSBruce Mitchener         Error
312e1cfbc79STodd Fiala         SetOptionValue (uint32_t option_idx, const char *option_arg,
313e1cfbc79STodd Fiala                         ExecutionContext *execution_context) override
3145a988416SJim Ingham         {
3155a988416SJim Ingham             Error error;
3163bcdfc0eSGreg Clayton             const int short_option = m_getopt_table[option_idx].val;
3175a988416SJim Ingham 
3185a988416SJim Ingham             switch (short_option)
3195a988416SJim Ingham             {
3205a988416SJim Ingham             case 'o':
3215a988416SJim Ingham                 m_use_one_liner = true;
3225a988416SJim Ingham                 m_one_liner = option_arg;
3235a988416SJim Ingham                 break;
3245a988416SJim Ingham 
3255a988416SJim Ingham             case 's':
3265a988416SJim Ingham                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
3275a988416SJim Ingham                                                                                      g_option_table[option_idx].enum_values,
3285a988416SJim Ingham                                                                                      eScriptLanguageNone,
3295a988416SJim Ingham                                                                                      error);
3305a988416SJim Ingham 
3315a988416SJim Ingham                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
3325a988416SJim Ingham                 {
3335a988416SJim Ingham                     m_use_script_language = true;
3345a988416SJim Ingham                 }
3355a988416SJim Ingham                 else
3365a988416SJim Ingham                 {
3375a988416SJim Ingham                     m_use_script_language = false;
3385a988416SJim Ingham                 }
3395a988416SJim Ingham                 break;
3405a988416SJim Ingham 
3415a988416SJim Ingham             case 'e':
3425a988416SJim Ingham                 {
3435a988416SJim Ingham                     bool success = false;
3445a988416SJim Ingham                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
3455a988416SJim Ingham                     if (!success)
3465a988416SJim Ingham                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
3475a988416SJim Ingham                 }
3485a988416SJim Ingham                 break;
3495a988416SJim Ingham 
3505a988416SJim Ingham             case 'F':
3515a988416SJim Ingham                 m_use_one_liner = false;
3525a988416SJim Ingham                 m_use_script_language = true;
3535a988416SJim Ingham                 m_function_name.assign(option_arg);
3545a988416SJim Ingham                 break;
3555a988416SJim Ingham 
35633df7cd3SJim Ingham             case 'D':
35733df7cd3SJim Ingham                 m_use_dummy = true;
35833df7cd3SJim Ingham                 break;
35933df7cd3SJim Ingham 
3605a988416SJim Ingham             default:
3615a988416SJim Ingham                 break;
3625a988416SJim Ingham             }
3635a988416SJim Ingham             return error;
3645a988416SJim Ingham         }
365c8ecc2a9SEugene Zelenko 
3665a988416SJim Ingham         void
367e1cfbc79STodd Fiala         OptionParsingStarting (ExecutionContext *execution_context) override
3685a988416SJim Ingham         {
3695a988416SJim Ingham             m_use_commands = true;
3705a988416SJim Ingham             m_use_script_language = false;
3715a988416SJim Ingham             m_script_language = eScriptLanguageNone;
3725a988416SJim Ingham 
3735a988416SJim Ingham             m_use_one_liner = false;
3745a988416SJim Ingham             m_stop_on_error = true;
3755a988416SJim Ingham             m_one_liner.clear();
3765a988416SJim Ingham             m_function_name.clear();
37733df7cd3SJim Ingham             m_use_dummy = false;
3785a988416SJim Ingham         }
3795a988416SJim Ingham 
3805a988416SJim Ingham         const OptionDefinition*
38113d21e9aSBruce Mitchener         GetDefinitions () override
3825a988416SJim Ingham         {
3835a988416SJim Ingham             return g_option_table;
3845a988416SJim Ingham         }
3855a988416SJim Ingham 
3865a988416SJim Ingham         // Options table: Required for subclasses of Options.
3875a988416SJim Ingham 
3885a988416SJim Ingham         static OptionDefinition g_option_table[];
3895a988416SJim Ingham 
3905a988416SJim Ingham         // Instance variables to hold the values for command options.
3915a988416SJim Ingham 
3925a988416SJim Ingham         bool m_use_commands;
3935a988416SJim Ingham         bool m_use_script_language;
3945a988416SJim Ingham         lldb::ScriptLanguage m_script_language;
3955a988416SJim Ingham 
3965a988416SJim Ingham         // Instance variables to hold the values for one_liner options.
3975a988416SJim Ingham         bool m_use_one_liner;
3985a988416SJim Ingham         std::string m_one_liner;
3995a988416SJim Ingham         bool m_stop_on_error;
4005a988416SJim Ingham         std::string m_function_name;
40133df7cd3SJim Ingham         bool m_use_dummy;
4025a988416SJim Ingham     };
4035a988416SJim Ingham 
4045a988416SJim Ingham protected:
40513d21e9aSBruce Mitchener     bool
40613d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
40730fdc8d8SChris Lattner     {
40833df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
40930fdc8d8SChris Lattner 
410c8ecc2a9SEugene Zelenko         if (target == nullptr)
41130fdc8d8SChris Lattner         {
41230fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
41330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
41430fdc8d8SChris Lattner             return false;
41530fdc8d8SChris Lattner         }
41630fdc8d8SChris Lattner 
41730fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
41830fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
41930fdc8d8SChris Lattner 
42030fdc8d8SChris Lattner         if (num_breakpoints == 0)
42130fdc8d8SChris Lattner         {
42230fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist to have commands added");
42330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
42430fdc8d8SChris Lattner             return false;
42530fdc8d8SChris Lattner         }
42630fdc8d8SChris Lattner 
427c8ecc2a9SEugene Zelenko         if (!m_options.m_use_script_language && !m_options.m_function_name.empty())
4288d4a8010SEnrico Granata         {
4298d4a8010SEnrico Granata             result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
4308d4a8010SEnrico Granata             result.SetStatus (eReturnStatusFailed);
4318d4a8010SEnrico Granata             return false;
4328d4a8010SEnrico Granata         }
4338d4a8010SEnrico Granata 
43430fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
4355e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
43630fdc8d8SChris Lattner 
437b5796cb4SJim Ingham         m_bp_options_vec.clear();
438b5796cb4SJim Ingham 
43930fdc8d8SChris Lattner         if (result.Succeeded())
44030fdc8d8SChris Lattner         {
441c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
442d9916eaeSJim Ingham 
443c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
44430fdc8d8SChris Lattner             {
44530fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
44630fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
44730fdc8d8SChris Lattner                 {
44830fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
449c8ecc2a9SEugene Zelenko                     BreakpointOptions *bp_options = nullptr;
45039d7d4f0SJohnny Chen                     if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
45139d7d4f0SJohnny Chen                     {
45239d7d4f0SJohnny Chen                         // This breakpoint does not have an associated location.
45339d7d4f0SJohnny Chen                         bp_options = bp->GetOptions();
45439d7d4f0SJohnny Chen                     }
45539d7d4f0SJohnny Chen                     else
45630fdc8d8SChris Lattner                     {
45730fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
45839d7d4f0SJohnny Chen                         // This breakpoint does have an associated location.
45939d7d4f0SJohnny Chen                         // Get its breakpoint options.
46030fdc8d8SChris Lattner                         if (bp_loc_sp)
46139d7d4f0SJohnny Chen                             bp_options = bp_loc_sp->GetLocationOptions();
46239d7d4f0SJohnny Chen                     }
463b5796cb4SJim Ingham                     if (bp_options)
464b5796cb4SJim Ingham                         m_bp_options_vec.push_back (bp_options);
465b5796cb4SJim Ingham                 }
466b5796cb4SJim Ingham             }
46739d7d4f0SJohnny Chen 
46839d7d4f0SJohnny Chen             // If we are using script language, get the script interpreter
46939d7d4f0SJohnny Chen             // in order to set or collect command callback.  Otherwise, call
47039d7d4f0SJohnny Chen             // the methods associated with this object.
47130fdc8d8SChris Lattner             if (m_options.m_use_script_language)
47230fdc8d8SChris Lattner             {
473b5796cb4SJim Ingham                 ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
47439d7d4f0SJohnny Chen                 // Special handling for one-liner specified inline.
47539d7d4f0SJohnny Chen                 if (m_options.m_use_one_liner)
4768d4a8010SEnrico Granata                 {
477b5796cb4SJim Ingham                     script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
47839d7d4f0SJohnny Chen                                                                  m_options.m_one_liner.c_str());
4798d4a8010SEnrico Granata                 }
480c8ecc2a9SEugene Zelenko                 else if (!m_options.m_function_name.empty())
4818d4a8010SEnrico Granata                 {
482b5796cb4SJim Ingham                     script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
483d80102e4SJim Ingham                                                                          m_options.m_function_name.c_str());
4848d4a8010SEnrico Granata                 }
48594de55d5SJohnny Chen                 else
4868d4a8010SEnrico Granata                 {
487b5796cb4SJim Ingham                     script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
48830fdc8d8SChris Lattner                                                                             result);
48930fdc8d8SChris Lattner                 }
4908d4a8010SEnrico Granata             }
49130fdc8d8SChris Lattner             else
49230fdc8d8SChris Lattner             {
49339d7d4f0SJohnny Chen                 // Special handling for one-liner specified inline.
49439d7d4f0SJohnny Chen                 if (m_options.m_use_one_liner)
495b5796cb4SJim Ingham                     SetBreakpointCommandCallback (m_bp_options_vec,
49639d7d4f0SJohnny Chen                                                   m_options.m_one_liner.c_str());
49739d7d4f0SJohnny Chen                 else
498b5796cb4SJim Ingham                     CollectDataForBreakpointCommandCallback (m_bp_options_vec,
499b132097bSGreg Clayton                                                              result);
50030fdc8d8SChris Lattner             }
50130fdc8d8SChris Lattner         }
50230fdc8d8SChris Lattner 
50330fdc8d8SChris Lattner         return result.Succeeded();
50430fdc8d8SChris Lattner     }
50530fdc8d8SChris Lattner 
5065a988416SJim Ingham private:
5075a988416SJim Ingham     CommandOptions m_options;
508b5796cb4SJim Ingham     std::vector<BreakpointOptions *> m_bp_options_vec;  // This stores the breakpoint options that we are currently
509b5796cb4SJim Ingham                                                         // collecting commands for.  In the CollectData... calls we need
510b5796cb4SJim Ingham                                                         // to hand this off to the IOHandler, which may run asynchronously.
511b5796cb4SJim Ingham                                                         // So we have to have some way to keep it alive, and not leak it.
512b5796cb4SJim Ingham                                                         // Making it an ivar of the command object, which never goes away
513b5796cb4SJim Ingham                                                         // achieves this.  Note that if we were able to run
514b5796cb4SJim Ingham                                                         // the same command concurrently in one interpreter we'd have to
515b5796cb4SJim Ingham                                                         // make this "per invocation".  But there are many more reasons
516b5796cb4SJim Ingham                                                         // why it is not in general safe to do that in lldb at present,
517b5796cb4SJim Ingham                                                         // so it isn't worthwhile to come up with a more complex mechanism
518b5796cb4SJim Ingham                                                         // to address this particular weakness right now.
5195a988416SJim Ingham     static const char *g_reader_instructions;
5205a988416SJim Ingham };
5215a988416SJim Ingham 
5225a988416SJim Ingham const char *
52344d93782SGreg Clayton CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.\n";
5245a988416SJim Ingham 
5255a988416SJim Ingham // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
5265a988416SJim Ingham // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
5275a988416SJim Ingham 
5285a988416SJim Ingham static OptionEnumValueElement
5295a988416SJim Ingham g_script_option_enumeration[4] =
53030fdc8d8SChris Lattner {
5315a988416SJim Ingham     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
5325a988416SJim Ingham     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
5335a988416SJim Ingham     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
534c8ecc2a9SEugene Zelenko     { 0,                      nullptr,           nullptr }
5355a988416SJim Ingham };
53630fdc8d8SChris Lattner 
5375a988416SJim Ingham OptionDefinition
5385a988416SJim Ingham CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
53930fdc8d8SChris Lattner {
540*ac9c3a62SKate Stone   // clang-format off
541*ac9c3a62SKate Stone   {LLDB_OPT_SET_1,   false, "one-liner",         'o', OptionParser::eRequiredArgument, nullptr, nullptr,                     0, eArgTypeOneLiner,       "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
542*ac9c3a62SKate Stone   {LLDB_OPT_SET_ALL, false, "stop-on-error",     'e', OptionParser::eRequiredArgument, nullptr, nullptr,                     0, eArgTypeBoolean,        "Specify whether breakpoint command execution should terminate on error." },
543*ac9c3a62SKate Stone   {LLDB_OPT_SET_ALL, false, "script-type",       's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone,           "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
544*ac9c3a62SKate Stone   {LLDB_OPT_SET_2,   false, "python-function",   'F', OptionParser::eRequiredArgument, nullptr, nullptr,                     0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
545*ac9c3a62SKate Stone   {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument,       nullptr, nullptr,                     0, eArgTypeNone,           "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
546c8ecc2a9SEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
547*ac9c3a62SKate Stone   // clang-format on
5485a988416SJim Ingham };
54930fdc8d8SChris Lattner 
55030fdc8d8SChris Lattner //-------------------------------------------------------------------------
55193e0f19fSCaroline Tice // CommandObjectBreakpointCommandDelete
55230fdc8d8SChris Lattner //-------------------------------------------------------------------------
55330fdc8d8SChris Lattner 
5545a988416SJim Ingham class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
5555a988416SJim Ingham {
5565a988416SJim Ingham public:
5575a988416SJim Ingham     CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
5585a988416SJim Ingham         CommandObjectParsed(interpreter,
55993e0f19fSCaroline Tice                             "delete",
56093e0f19fSCaroline Tice                             "Delete the set of commands from a breakpoint.",
561c8ecc2a9SEugene Zelenko                             nullptr),
562e1cfbc79STodd Fiala         m_options()
56330fdc8d8SChris Lattner     {
564405fe67fSCaroline Tice         CommandArgumentEntry arg;
565405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
566405fe67fSCaroline Tice 
567405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
568405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
569405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
570405fe67fSCaroline Tice 
571405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
572405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
573405fe67fSCaroline Tice 
574405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
575405fe67fSCaroline Tice         m_arguments.push_back (arg);
57630fdc8d8SChris Lattner     }
57730fdc8d8SChris Lattner 
578c8ecc2a9SEugene Zelenko     ~CommandObjectBreakpointCommandDelete() override = default;
5795a988416SJim Ingham 
58013d21e9aSBruce Mitchener     Options *
58113d21e9aSBruce Mitchener     GetOptions () override
58233df7cd3SJim Ingham     {
58333df7cd3SJim Ingham         return &m_options;
58433df7cd3SJim Ingham     }
58533df7cd3SJim Ingham 
58633df7cd3SJim Ingham     class CommandOptions : public Options
58733df7cd3SJim Ingham     {
58833df7cd3SJim Ingham     public:
589e1cfbc79STodd Fiala         CommandOptions() :
590e1cfbc79STodd Fiala             Options(),
59133df7cd3SJim Ingham             m_use_dummy(false)
59233df7cd3SJim Ingham         {
59333df7cd3SJim Ingham         }
59433df7cd3SJim Ingham 
595c8ecc2a9SEugene Zelenko         ~CommandOptions() override = default;
59633df7cd3SJim Ingham 
59713d21e9aSBruce Mitchener         Error
598e1cfbc79STodd Fiala         SetOptionValue (uint32_t option_idx, const char *option_arg,
599e1cfbc79STodd Fiala                         ExecutionContext *execution_context) override
60033df7cd3SJim Ingham         {
60133df7cd3SJim Ingham             Error error;
60233df7cd3SJim Ingham             const int short_option = m_getopt_table[option_idx].val;
60333df7cd3SJim Ingham 
60433df7cd3SJim Ingham             switch (short_option)
60533df7cd3SJim Ingham             {
60633df7cd3SJim Ingham                 case 'D':
60733df7cd3SJim Ingham                     m_use_dummy = true;
60833df7cd3SJim Ingham                     break;
60933df7cd3SJim Ingham 
61033df7cd3SJim Ingham                 default:
61133df7cd3SJim Ingham                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
61233df7cd3SJim Ingham                     break;
61333df7cd3SJim Ingham             }
61433df7cd3SJim Ingham 
61533df7cd3SJim Ingham             return error;
61633df7cd3SJim Ingham         }
61733df7cd3SJim Ingham 
61833df7cd3SJim Ingham         void
619e1cfbc79STodd Fiala         OptionParsingStarting (ExecutionContext *execution_context) override
62033df7cd3SJim Ingham         {
62133df7cd3SJim Ingham             m_use_dummy = false;
62233df7cd3SJim Ingham         }
62333df7cd3SJim Ingham 
62433df7cd3SJim Ingham         const OptionDefinition*
62513d21e9aSBruce Mitchener         GetDefinitions () override
62633df7cd3SJim Ingham         {
62733df7cd3SJim Ingham             return g_option_table;
62833df7cd3SJim Ingham         }
62933df7cd3SJim Ingham 
63033df7cd3SJim Ingham         // Options table: Required for subclasses of Options.
63133df7cd3SJim Ingham 
63233df7cd3SJim Ingham         static OptionDefinition g_option_table[];
63333df7cd3SJim Ingham 
63433df7cd3SJim Ingham         // Instance variables to hold the values for command options.
63533df7cd3SJim Ingham         bool m_use_dummy;
63633df7cd3SJim Ingham     };
63733df7cd3SJim Ingham 
6385a988416SJim Ingham protected:
63913d21e9aSBruce Mitchener     bool
64013d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
64130fdc8d8SChris Lattner     {
64233df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
64330fdc8d8SChris Lattner 
644c8ecc2a9SEugene Zelenko         if (target == nullptr)
64530fdc8d8SChris Lattner         {
64693e0f19fSCaroline Tice             result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
64730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
64830fdc8d8SChris Lattner             return false;
64930fdc8d8SChris Lattner         }
65030fdc8d8SChris Lattner 
65130fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
65230fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
65330fdc8d8SChris Lattner 
65430fdc8d8SChris Lattner         if (num_breakpoints == 0)
65530fdc8d8SChris Lattner         {
65693e0f19fSCaroline Tice             result.AppendError ("No breakpoints exist to have commands deleted");
65730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
65830fdc8d8SChris Lattner             return false;
65930fdc8d8SChris Lattner         }
66030fdc8d8SChris Lattner 
66130fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
66230fdc8d8SChris Lattner         {
66393e0f19fSCaroline Tice             result.AppendError ("No breakpoint specified from which to delete the commands");
66430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
66530fdc8d8SChris Lattner             return false;
66630fdc8d8SChris Lattner         }
66730fdc8d8SChris Lattner 
66830fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
6695e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
67030fdc8d8SChris Lattner 
67130fdc8d8SChris Lattner         if (result.Succeeded())
67230fdc8d8SChris Lattner         {
673c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
674c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
67530fdc8d8SChris Lattner             {
67630fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
67730fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
67830fdc8d8SChris Lattner                 {
67930fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
68030fdc8d8SChris Lattner                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
68130fdc8d8SChris Lattner                     {
68230fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
68330fdc8d8SChris Lattner                         if (bp_loc_sp)
68430fdc8d8SChris Lattner                             bp_loc_sp->ClearCallback();
68530fdc8d8SChris Lattner                         else
68630fdc8d8SChris Lattner                         {
68730fdc8d8SChris Lattner                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
68830fdc8d8SChris Lattner                                                          cur_bp_id.GetBreakpointID(),
68930fdc8d8SChris Lattner                                                          cur_bp_id.GetLocationID());
69030fdc8d8SChris Lattner                             result.SetStatus (eReturnStatusFailed);
69130fdc8d8SChris Lattner                             return false;
69230fdc8d8SChris Lattner                         }
69330fdc8d8SChris Lattner                     }
69430fdc8d8SChris Lattner                     else
69530fdc8d8SChris Lattner                     {
69630fdc8d8SChris Lattner                         bp->ClearCallback();
69730fdc8d8SChris Lattner                     }
69830fdc8d8SChris Lattner                 }
69930fdc8d8SChris Lattner             }
70030fdc8d8SChris Lattner         }
70130fdc8d8SChris Lattner         return result.Succeeded();
70230fdc8d8SChris Lattner     }
703c8ecc2a9SEugene Zelenko 
70433df7cd3SJim Ingham private:
70533df7cd3SJim Ingham     CommandOptions m_options;
7065a988416SJim Ingham };
70730fdc8d8SChris Lattner 
70833df7cd3SJim Ingham OptionDefinition
70933df7cd3SJim Ingham CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
71033df7cd3SJim Ingham {
711*ac9c3a62SKate Stone   // clang-format off
712*ac9c3a62SKate Stone   {LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
713c8ecc2a9SEugene Zelenko   {0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr}
714*ac9c3a62SKate Stone   // clang-format on
71533df7cd3SJim Ingham };
71633df7cd3SJim Ingham 
71730fdc8d8SChris Lattner //-------------------------------------------------------------------------
71830fdc8d8SChris Lattner // CommandObjectBreakpointCommandList
71930fdc8d8SChris Lattner //-------------------------------------------------------------------------
72030fdc8d8SChris Lattner 
7215a988416SJim Ingham class CommandObjectBreakpointCommandList : public CommandObjectParsed
7225a988416SJim Ingham {
7235a988416SJim Ingham public:
7245a988416SJim Ingham     CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
7255a988416SJim Ingham         CommandObjectParsed(interpreter,
726a7015092SGreg Clayton                             "list",
72730fdc8d8SChris Lattner                             "List the script or set of commands to be executed when the breakpoint is hit.",
728c8ecc2a9SEugene Zelenko                             nullptr)
72930fdc8d8SChris Lattner     {
730405fe67fSCaroline Tice         CommandArgumentEntry arg;
731405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
732405fe67fSCaroline Tice 
733405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
734405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
735405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
736405fe67fSCaroline Tice 
737405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
738405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
739405fe67fSCaroline Tice 
740405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
741405fe67fSCaroline Tice         m_arguments.push_back (arg);
74230fdc8d8SChris Lattner     }
74330fdc8d8SChris Lattner 
744c8ecc2a9SEugene Zelenko     ~CommandObjectBreakpointCommandList() override = default;
74530fdc8d8SChris Lattner 
7465a988416SJim Ingham protected:
74713d21e9aSBruce Mitchener     bool
7485a988416SJim Ingham     DoExecute (Args& command,
74913d21e9aSBruce Mitchener              CommandReturnObject &result) override
75030fdc8d8SChris Lattner     {
751a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
75230fdc8d8SChris Lattner 
753c8ecc2a9SEugene Zelenko         if (target == nullptr)
75430fdc8d8SChris Lattner         {
75530fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
75630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
75730fdc8d8SChris Lattner             return false;
75830fdc8d8SChris Lattner         }
75930fdc8d8SChris Lattner 
76030fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
76130fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
76230fdc8d8SChris Lattner 
76330fdc8d8SChris Lattner         if (num_breakpoints == 0)
76430fdc8d8SChris Lattner         {
76530fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist for which to list commands");
76630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
76730fdc8d8SChris Lattner             return false;
76830fdc8d8SChris Lattner         }
76930fdc8d8SChris Lattner 
77030fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
77130fdc8d8SChris Lattner         {
77230fdc8d8SChris Lattner             result.AppendError ("No breakpoint specified for which to list the commands");
77330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
77430fdc8d8SChris Lattner             return false;
77530fdc8d8SChris Lattner         }
77630fdc8d8SChris Lattner 
77730fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
7785e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
77930fdc8d8SChris Lattner 
78030fdc8d8SChris Lattner         if (result.Succeeded())
78130fdc8d8SChris Lattner         {
782c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
783c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
78430fdc8d8SChris Lattner             {
78530fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
78630fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
78730fdc8d8SChris Lattner                 {
78830fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
78930fdc8d8SChris Lattner 
79030fdc8d8SChris Lattner                     if (bp)
79130fdc8d8SChris Lattner                     {
792c8ecc2a9SEugene Zelenko                         const BreakpointOptions *bp_options = nullptr;
79330fdc8d8SChris Lattner                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
79430fdc8d8SChris Lattner                         {
79530fdc8d8SChris Lattner                             BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
79630fdc8d8SChris Lattner                             if (bp_loc_sp)
79705407f6bSJim Ingham                                 bp_options = bp_loc_sp->GetOptionsNoCreate();
79830fdc8d8SChris Lattner                             else
79930fdc8d8SChris Lattner                             {
80030fdc8d8SChris Lattner                                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
80130fdc8d8SChris Lattner                                                              cur_bp_id.GetBreakpointID(),
80230fdc8d8SChris Lattner                                                              cur_bp_id.GetLocationID());
80330fdc8d8SChris Lattner                                 result.SetStatus (eReturnStatusFailed);
80430fdc8d8SChris Lattner                                 return false;
80530fdc8d8SChris Lattner                             }
80630fdc8d8SChris Lattner                         }
80730fdc8d8SChris Lattner                         else
80830fdc8d8SChris Lattner                         {
80930fdc8d8SChris Lattner                             bp_options = bp->GetOptions();
81030fdc8d8SChris Lattner                         }
81130fdc8d8SChris Lattner 
81230fdc8d8SChris Lattner                         if (bp_options)
81330fdc8d8SChris Lattner                         {
81430fdc8d8SChris Lattner                             StreamString id_str;
815e16c50a1SJim Ingham                             BreakpointID::GetCanonicalReference (&id_str,
816e16c50a1SJim Ingham                                                                  cur_bp_id.GetBreakpointID(),
817e16c50a1SJim Ingham                                                                  cur_bp_id.GetLocationID());
8181b54c88cSJim Ingham                             const Baton *baton = bp_options->GetBaton();
81930fdc8d8SChris Lattner                             if (baton)
82030fdc8d8SChris Lattner                             {
82130fdc8d8SChris Lattner                                 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
82230fdc8d8SChris Lattner                                 result.GetOutputStream().IndentMore ();
82330fdc8d8SChris Lattner                                 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
82430fdc8d8SChris Lattner                                 result.GetOutputStream().IndentLess ();
82530fdc8d8SChris Lattner                             }
82630fdc8d8SChris Lattner                             else
82730fdc8d8SChris Lattner                             {
828e16c50a1SJim Ingham                                 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
829e16c50a1SJim Ingham                                                                 id_str.GetData());
83030fdc8d8SChris Lattner                             }
83130fdc8d8SChris Lattner                         }
83230fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishResult);
83330fdc8d8SChris Lattner                     }
83430fdc8d8SChris Lattner                     else
83530fdc8d8SChris Lattner                     {
83630fdc8d8SChris Lattner                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
83730fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusFailed);
83830fdc8d8SChris Lattner                     }
83930fdc8d8SChris Lattner                 }
84030fdc8d8SChris Lattner             }
84130fdc8d8SChris Lattner         }
84230fdc8d8SChris Lattner 
84330fdc8d8SChris Lattner         return result.Succeeded();
84430fdc8d8SChris Lattner     }
8455a988416SJim Ingham };
84630fdc8d8SChris Lattner 
84730fdc8d8SChris Lattner //-------------------------------------------------------------------------
84830fdc8d8SChris Lattner // CommandObjectBreakpointCommand
84930fdc8d8SChris Lattner //-------------------------------------------------------------------------
85030fdc8d8SChris Lattner 
8517428a18cSKate Stone CommandObjectBreakpointCommand::CommandObjectBreakpointCommand(CommandInterpreter &interpreter)
8527428a18cSKate Stone     : CommandObjectMultiword(
8537428a18cSKate Stone           interpreter, "command",
8547428a18cSKate Stone           "Commands for adding, removing and listing LLDB commands executed when a breakpoint is hit.",
85530fdc8d8SChris Lattner           "command <sub-command> [<sub-command-options>] <breakpoint-id>")
85630fdc8d8SChris Lattner {
857a7015092SGreg Clayton     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
85893e0f19fSCaroline Tice     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
859a7015092SGreg Clayton     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
86030fdc8d8SChris Lattner 
86130fdc8d8SChris Lattner     add_command_object->SetCommandName ("breakpoint command add");
86293e0f19fSCaroline Tice     delete_command_object->SetCommandName ("breakpoint command delete");
86330fdc8d8SChris Lattner     list_command_object->SetCommandName ("breakpoint command list");
86430fdc8d8SChris Lattner 
86523f59509SGreg Clayton     LoadSubCommand ("add",    add_command_object);
86623f59509SGreg Clayton     LoadSubCommand ("delete", delete_command_object);
86723f59509SGreg Clayton     LoadSubCommand ("list",   list_command_object);
86830fdc8d8SChris Lattner }
86930fdc8d8SChris Lattner 
870c8ecc2a9SEugene Zelenko CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand() = default;
871