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
12*c8ecc2a9SEugene Zelenko // Other libraries and framework includes
13*c8ecc2a9SEugene 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:
395a988416SJim Ingham     CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
405a988416SJim Ingham         CommandObjectParsed(interpreter,
41a7015092SGreg Clayton                             "add",
421bb0750bSJim Ingham                             "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit."
431bb0750bSJim Ingham                             "  If no breakpoint is specified, adds the commands to the last created breakpoint.",
44*c8ecc2a9SEugene Zelenko                             nullptr),
45c3d874a5SGreg Clayton         IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
46eb0103f2SGreg Clayton         m_options (interpreter)
4730fdc8d8SChris Lattner     {
4830fdc8d8SChris Lattner         SetHelpLong (
49ea671fbdSKate Stone R"(
50ea671fbdSKate Stone General information about entering breakpoint commands
51ea671fbdSKate Stone ------------------------------------------------------
52ea671fbdSKate Stone 
53ea671fbdSKate Stone )" "This command will prompt for commands to be executed when the specified \
54ea671fbdSKate Stone breakpoint is hit.  Each command is typed on its own line following the '> ' \
55ea671fbdSKate Stone prompt until 'DONE' is entered." R"(
56ea671fbdSKate Stone 
57ea671fbdSKate Stone )" "Syntactic errors may not be detected when initially entered, and many \
58ea671fbdSKate Stone malformed commands can silently fail when executed.  If your breakpoint commands \
59ea671fbdSKate Stone do not appear to be executing, double-check the command syntax." R"(
60ea671fbdSKate Stone 
61ea671fbdSKate Stone )" "Note: You may enter any debugger command exactly as you would at the debugger \
62ea671fbdSKate Stone prompt.  There is no limit to the number of commands supplied, but do NOT enter \
63ea671fbdSKate Stone more than one command per line." R"(
64ea671fbdSKate Stone 
65ea671fbdSKate Stone Special information about PYTHON breakpoint commands
66ea671fbdSKate Stone ----------------------------------------------------
67ea671fbdSKate Stone 
68ea671fbdSKate Stone )" "You may enter either one or more lines of Python, including function \
69ea671fbdSKate Stone definitions or calls to functions that will have been imported by the time \
70ea671fbdSKate Stone the code executes.  Single line breakpoint commands will be interpreted 'as is' \
71ea671fbdSKate Stone when the breakpoint is hit.  Multiple lines of Python will be wrapped in a \
72ea671fbdSKate Stone generated function, and a call to the function will be attached to the breakpoint." R"(
73ea671fbdSKate Stone 
74ea671fbdSKate Stone This auto-generated function is passed in three arguments:
75ea671fbdSKate Stone 
76ea671fbdSKate Stone     frame:  an lldb.SBFrame object for the frame which hit breakpoint.
77ea671fbdSKate Stone 
78ea671fbdSKate Stone     bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
79ea671fbdSKate Stone 
80ea671fbdSKate Stone     dict:   the python session dictionary hit.
81ea671fbdSKate Stone 
82ea671fbdSKate Stone )" "When specifying a python function with the --python-function option, you need \
83ea671fbdSKate Stone to supply the function name prepended by the module name:" R"(
84ea671fbdSKate Stone 
85ea671fbdSKate Stone     --python-function myutils.breakpoint_callback
86ea671fbdSKate Stone 
87ea671fbdSKate Stone The function itself must have the following prototype:
88ea671fbdSKate Stone 
89ea671fbdSKate Stone def breakpoint_callback(frame, bp_loc, dict):
90ea671fbdSKate Stone   # Your code goes here
91ea671fbdSKate Stone 
92ea671fbdSKate Stone )" "The arguments are the same as the arguments passed to generated functions as \
93ea671fbdSKate Stone described above.  Note that the global variable 'lldb.frame' will NOT be updated when \
94ea671fbdSKate Stone this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
95ea671fbdSKate Stone can get you to the thread via frame.GetThread(), the thread can get you to the \
96ea671fbdSKate Stone process via thread.GetProcess(), and the process can get you back to the target \
97ea671fbdSKate Stone via process.GetTarget()." R"(
98ea671fbdSKate Stone 
99ea671fbdSKate Stone )" "Important Note: As Python code gets collected into functions, access to global \
100ea671fbdSKate Stone variables requires explicit scoping using the 'global' keyword.  Be sure to use correct \
101ea671fbdSKate Stone Python syntax, including indentation, when entering Python breakpoint commands." R"(
102ea671fbdSKate Stone 
103ea671fbdSKate Stone Example Python one-line breakpoint command:
104ea671fbdSKate Stone 
105ea671fbdSKate Stone (lldb) breakpoint command add -s python 1
106ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
107ea671fbdSKate Stone > print "Hit this breakpoint!"
108ea671fbdSKate Stone > DONE
109ea671fbdSKate Stone 
110ea671fbdSKate Stone As a convenience, this also works for a short Python one-liner:
111ea671fbdSKate Stone 
112ea671fbdSKate Stone (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
113ea671fbdSKate Stone (lldb) run
114ea671fbdSKate Stone Launching '.../a.out'  (x86_64)
115ea671fbdSKate Stone (lldb) Fri Sep 10 12:17:45 2010
116ea671fbdSKate Stone Process 21778 Stopped
117ea671fbdSKate Stone * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
118ea671fbdSKate Stone   36
119ea671fbdSKate Stone   37   	int c(int val)
120ea671fbdSKate Stone   38   	{
121ea671fbdSKate Stone   39 ->	    return val + 3;
122ea671fbdSKate Stone   40   	}
123ea671fbdSKate Stone   41
124ea671fbdSKate Stone   42   	int main (int argc, char const *argv[])
125ea671fbdSKate Stone 
126ea671fbdSKate Stone Example multiple line Python breakpoint command:
127ea671fbdSKate Stone 
128ea671fbdSKate Stone (lldb) breakpoint command add -s p 1
129ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
130ea671fbdSKate Stone > global bp_count
131ea671fbdSKate Stone > bp_count = bp_count + 1
132ea671fbdSKate Stone > print "Hit this breakpoint " + repr(bp_count) + " times!"
133ea671fbdSKate Stone > DONE
134ea671fbdSKate Stone 
135ea671fbdSKate Stone Example multiple line Python breakpoint command, using function definition:
136ea671fbdSKate Stone 
137ea671fbdSKate Stone (lldb) breakpoint command add -s python 1
138ea671fbdSKate Stone Enter your Python command(s). Type 'DONE' to end.
139ea671fbdSKate Stone > def breakpoint_output (bp_no):
140ea671fbdSKate Stone >     out_string = "Hit breakpoint number " + repr (bp_no)
141ea671fbdSKate Stone >     print out_string
142ea671fbdSKate Stone >     return True
143ea671fbdSKate Stone > breakpoint_output (1)
144ea671fbdSKate Stone > DONE
145ea671fbdSKate Stone 
146ea671fbdSKate Stone )" "In this case, since there is a reference to a global variable, \
147ea671fbdSKate Stone 'bp_count', you will also need to make sure 'bp_count' exists and is \
148ea671fbdSKate Stone initialized:" R"(
149ea671fbdSKate Stone 
150ea671fbdSKate Stone (lldb) script
151ea671fbdSKate Stone >>> bp_count = 0
152ea671fbdSKate Stone >>> quit()
153ea671fbdSKate Stone 
154ea671fbdSKate Stone )" "Your Python code, however organized, can optionally return a value.  \
155ea671fbdSKate Stone If the returned value is False, that tells LLDB not to stop at the breakpoint \
156ea671fbdSKate Stone to which the code is associated. Returning anything other than False, or even \
157ea671fbdSKate Stone returning None, or even omitting a return statement entirely, will cause \
158ea671fbdSKate Stone LLDB to stop." R"(
159ea671fbdSKate Stone 
160ea671fbdSKate Stone )" "Final Note: A warning that no breakpoint command was generated when there \
161ea671fbdSKate Stone are no syntax errors may indicate that a function was declared but never called."
162ea671fbdSKate Stone         );
163405fe67fSCaroline Tice 
164405fe67fSCaroline Tice         CommandArgumentEntry arg;
165405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
166405fe67fSCaroline Tice 
167405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
168405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
1691bb0750bSJim Ingham         bp_id_arg.arg_repetition = eArgRepeatOptional;
170405fe67fSCaroline Tice 
171405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
172405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
173405fe67fSCaroline Tice 
174405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
175405fe67fSCaroline Tice         m_arguments.push_back (arg);
17630fdc8d8SChris Lattner     }
17730fdc8d8SChris Lattner 
178*c8ecc2a9SEugene Zelenko     ~CommandObjectBreakpointCommandAdd() override = default;
1795a988416SJim Ingham 
18013d21e9aSBruce Mitchener     Options *
18113d21e9aSBruce Mitchener     GetOptions () override
1825a988416SJim Ingham     {
1835a988416SJim Ingham         return &m_options;
1845a988416SJim Ingham     }
1855a988416SJim Ingham 
18613d21e9aSBruce Mitchener     void
18713d21e9aSBruce Mitchener     IOHandlerActivated (IOHandler &io_handler) override
18844d93782SGreg Clayton     {
18944d93782SGreg Clayton         StreamFileSP output_sp(io_handler.GetOutputStreamFile());
19044d93782SGreg Clayton         if (output_sp)
19144d93782SGreg Clayton         {
19244d93782SGreg Clayton             output_sp->PutCString(g_reader_instructions);
19344d93782SGreg Clayton             output_sp->Flush();
19444d93782SGreg Clayton         }
19544d93782SGreg Clayton     }
19644d93782SGreg Clayton 
19713d21e9aSBruce Mitchener     void
19813d21e9aSBruce Mitchener     IOHandlerInputComplete (IOHandler &io_handler, std::string &line) override
19944d93782SGreg Clayton     {
20044d93782SGreg Clayton         io_handler.SetIsDone(true);
20144d93782SGreg Clayton 
202b5796cb4SJim Ingham         std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
203b5796cb4SJim Ingham         for (BreakpointOptions *bp_options : *bp_options_vec)
20444d93782SGreg Clayton         {
205b5796cb4SJim Ingham             if (!bp_options)
206b5796cb4SJim Ingham                 continue;
207b5796cb4SJim Ingham 
20844d93782SGreg Clayton             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
209*c8ecc2a9SEugene Zelenko             if (data_ap)
21044d93782SGreg Clayton             {
21144d93782SGreg Clayton                 data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
21244d93782SGreg Clayton                 BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
21344d93782SGreg Clayton                 bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
21444d93782SGreg Clayton             }
21544d93782SGreg Clayton         }
21644d93782SGreg Clayton     }
21744d93782SGreg Clayton 
2185a988416SJim Ingham     void
219b5796cb4SJim Ingham     CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
2205a988416SJim Ingham                                              CommandReturnObject &result)
2215a988416SJim Ingham     {
22244d93782SGreg Clayton         m_interpreter.GetLLDBCommandsFromIOHandler ("> ",           // Prompt
22344d93782SGreg Clayton                                                     *this,          // IOHandlerDelegate
22444d93782SGreg Clayton                                                     true,           // Run IOHandler in async mode
225b5796cb4SJim Ingham                                                     &bp_options_vec);    // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
2265a988416SJim Ingham     }
2275a988416SJim Ingham 
2285a988416SJim Ingham     /// Set a one-liner as the callback for the breakpoint.
2295a988416SJim Ingham     void
230b5796cb4SJim Ingham     SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
2315a988416SJim Ingham                                   const char *oneliner)
2325a988416SJim Ingham     {
233b5796cb4SJim Ingham         for (auto bp_options : bp_options_vec)
234b5796cb4SJim Ingham         {
2357b0992d9SGreg Clayton             std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
2365a988416SJim Ingham 
2375a988416SJim Ingham             // It's necessary to set both user_source and script_source to the oneliner.
2385a988416SJim Ingham             // The former is used to generate callback description (as in breakpoint command list)
2395a988416SJim Ingham             // while the latter is used for Python to interpret during the actual callback.
2405a988416SJim Ingham             data_ap->user_source.AppendString (oneliner);
2415a988416SJim Ingham             data_ap->script_source.assign (oneliner);
2425a988416SJim Ingham             data_ap->stop_on_error = m_options.m_stop_on_error;
2435a988416SJim Ingham 
2445a988416SJim Ingham             BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
2455a988416SJim Ingham             bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
246b5796cb4SJim Ingham         }
2475a988416SJim Ingham     }
2485a988416SJim Ingham 
2495a988416SJim Ingham     static bool
2505a988416SJim Ingham     BreakpointOptionsCallbackFunction (void *baton,
2515a988416SJim Ingham                                        StoppointCallbackContext *context,
2525a988416SJim Ingham                                        lldb::user_id_t break_id,
2535a988416SJim Ingham                                        lldb::user_id_t break_loc_id)
2545a988416SJim Ingham     {
2555a988416SJim Ingham         bool ret_value = true;
256*c8ecc2a9SEugene Zelenko         if (baton == nullptr)
2575a988416SJim Ingham             return true;
2585a988416SJim Ingham 
2595a988416SJim Ingham         BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
2605a988416SJim Ingham         StringList &commands = data->user_source;
2615a988416SJim Ingham 
2625a988416SJim Ingham         if (commands.GetSize() > 0)
2635a988416SJim Ingham         {
2645a988416SJim Ingham             ExecutionContext exe_ctx (context->exe_ctx_ref);
2655a988416SJim Ingham             Target *target = exe_ctx.GetTargetPtr();
2665a988416SJim Ingham             if (target)
2675a988416SJim Ingham             {
2685a988416SJim Ingham                 CommandReturnObject result;
2695a988416SJim Ingham                 Debugger &debugger = target->GetDebugger();
2705a988416SJim Ingham                 // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
2715a988416SJim Ingham                 // if the debugger is set up that way.
2725a988416SJim Ingham 
2735a988416SJim Ingham                 StreamSP output_stream (debugger.GetAsyncOutputStream());
2745a988416SJim Ingham                 StreamSP error_stream (debugger.GetAsyncErrorStream());
2755a988416SJim Ingham                 result.SetImmediateOutputStream (output_stream);
2765a988416SJim Ingham                 result.SetImmediateErrorStream (error_stream);
2775a988416SJim Ingham 
27826c7bf93SJim Ingham                 CommandInterpreterRunOptions options;
27926c7bf93SJim Ingham                 options.SetStopOnContinue(true);
28026c7bf93SJim Ingham                 options.SetStopOnError (data->stop_on_error);
28126c7bf93SJim Ingham                 options.SetEchoCommands (true);
28226c7bf93SJim Ingham                 options.SetPrintResults (true);
28326c7bf93SJim Ingham                 options.SetAddToHistory (false);
2845a988416SJim Ingham 
2855a988416SJim Ingham                 debugger.GetCommandInterpreter().HandleCommands (commands,
2865a988416SJim Ingham                                                                  &exe_ctx,
28726c7bf93SJim Ingham                                                                  options,
2885a988416SJim Ingham                                                                  result);
2895a988416SJim Ingham                 result.GetImmediateOutputStream()->Flush();
2905a988416SJim Ingham                 result.GetImmediateErrorStream()->Flush();
2915a988416SJim Ingham            }
2925a988416SJim Ingham         }
2935a988416SJim Ingham         return ret_value;
2945a988416SJim Ingham     }
2955a988416SJim Ingham 
2965a988416SJim Ingham     class CommandOptions : public Options
2975a988416SJim Ingham     {
2985a988416SJim Ingham     public:
2995a988416SJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
3005a988416SJim Ingham             Options (interpreter),
3015a988416SJim Ingham             m_use_commands (false),
3025a988416SJim Ingham             m_use_script_language (false),
3035a988416SJim Ingham             m_script_language (eScriptLanguageNone),
3045a988416SJim Ingham             m_use_one_liner (false),
3055a988416SJim Ingham             m_one_liner(),
3065a988416SJim Ingham             m_function_name()
30730fdc8d8SChris Lattner         {
30830fdc8d8SChris Lattner         }
30930fdc8d8SChris Lattner 
310*c8ecc2a9SEugene Zelenko         ~CommandOptions() override = default;
3115a988416SJim Ingham 
31213d21e9aSBruce Mitchener         Error
31313d21e9aSBruce Mitchener         SetOptionValue (uint32_t option_idx, const char *option_arg) 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         }
365*c8ecc2a9SEugene Zelenko 
3665a988416SJim Ingham         void
36713d21e9aSBruce Mitchener         OptionParsingStarting () 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 
410*c8ecc2a9SEugene 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 
427*c8ecc2a9SEugene 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();
449*c8ecc2a9SEugene 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                 }
480*c8ecc2a9SEugene 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."},
534*c8ecc2a9SEugene Zelenko     { 0,                      nullptr,           nullptr }
5355a988416SJim Ingham };
53630fdc8d8SChris Lattner 
5375a988416SJim Ingham OptionDefinition
5385a988416SJim Ingham CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
53930fdc8d8SChris Lattner {
540*c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner,
5415a988416SJim Ingham         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
54230fdc8d8SChris Lattner 
543*c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
5445a988416SJim Ingham         "Specify whether breakpoint command execution should terminate on error." },
54530fdc8d8SChris Lattner 
546*c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_ALL,   false, "script-type",     's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone,
5475a988416SJim Ingham         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
54830fdc8d8SChris Lattner 
549*c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_2,   false, "python-function",     'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction,
5505a988416SJim Ingham         "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
55139d7d4f0SJohnny Chen 
552*c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
55333df7cd3SJim Ingham         "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
55433df7cd3SJim Ingham 
555*c8ecc2a9SEugene Zelenko     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
5565a988416SJim Ingham };
55730fdc8d8SChris Lattner 
55830fdc8d8SChris Lattner //-------------------------------------------------------------------------
55993e0f19fSCaroline Tice // CommandObjectBreakpointCommandDelete
56030fdc8d8SChris Lattner //-------------------------------------------------------------------------
56130fdc8d8SChris Lattner 
5625a988416SJim Ingham class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
5635a988416SJim Ingham {
5645a988416SJim Ingham public:
5655a988416SJim Ingham     CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
5665a988416SJim Ingham         CommandObjectParsed(interpreter,
56793e0f19fSCaroline Tice                             "delete",
56893e0f19fSCaroline Tice                             "Delete the set of commands from a breakpoint.",
569*c8ecc2a9SEugene Zelenko                             nullptr),
57033df7cd3SJim Ingham         m_options (interpreter)
57130fdc8d8SChris Lattner     {
572405fe67fSCaroline Tice         CommandArgumentEntry arg;
573405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
574405fe67fSCaroline Tice 
575405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
576405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
577405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
578405fe67fSCaroline Tice 
579405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
580405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
581405fe67fSCaroline Tice 
582405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
583405fe67fSCaroline Tice         m_arguments.push_back (arg);
58430fdc8d8SChris Lattner     }
58530fdc8d8SChris Lattner 
586*c8ecc2a9SEugene Zelenko     ~CommandObjectBreakpointCommandDelete() override = default;
5875a988416SJim Ingham 
58813d21e9aSBruce Mitchener     Options *
58913d21e9aSBruce Mitchener     GetOptions () override
59033df7cd3SJim Ingham     {
59133df7cd3SJim Ingham         return &m_options;
59233df7cd3SJim Ingham     }
59333df7cd3SJim Ingham 
59433df7cd3SJim Ingham     class CommandOptions : public Options
59533df7cd3SJim Ingham     {
59633df7cd3SJim Ingham     public:
59733df7cd3SJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
59833df7cd3SJim Ingham             Options (interpreter),
59933df7cd3SJim Ingham             m_use_dummy (false)
60033df7cd3SJim Ingham         {
60133df7cd3SJim Ingham         }
60233df7cd3SJim Ingham 
603*c8ecc2a9SEugene Zelenko         ~CommandOptions() override = default;
60433df7cd3SJim Ingham 
60513d21e9aSBruce Mitchener         Error
60613d21e9aSBruce Mitchener         SetOptionValue (uint32_t option_idx, const char *option_arg) override
60733df7cd3SJim Ingham         {
60833df7cd3SJim Ingham             Error error;
60933df7cd3SJim Ingham             const int short_option = m_getopt_table[option_idx].val;
61033df7cd3SJim Ingham 
61133df7cd3SJim Ingham             switch (short_option)
61233df7cd3SJim Ingham             {
61333df7cd3SJim Ingham                 case 'D':
61433df7cd3SJim Ingham                     m_use_dummy = true;
61533df7cd3SJim Ingham                     break;
61633df7cd3SJim Ingham 
61733df7cd3SJim Ingham                 default:
61833df7cd3SJim Ingham                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
61933df7cd3SJim Ingham                     break;
62033df7cd3SJim Ingham             }
62133df7cd3SJim Ingham 
62233df7cd3SJim Ingham             return error;
62333df7cd3SJim Ingham         }
62433df7cd3SJim Ingham 
62533df7cd3SJim Ingham         void
62613d21e9aSBruce Mitchener         OptionParsingStarting () override
62733df7cd3SJim Ingham         {
62833df7cd3SJim Ingham             m_use_dummy = false;
62933df7cd3SJim Ingham         }
63033df7cd3SJim Ingham 
63133df7cd3SJim Ingham         const OptionDefinition*
63213d21e9aSBruce Mitchener         GetDefinitions () override
63333df7cd3SJim Ingham         {
63433df7cd3SJim Ingham             return g_option_table;
63533df7cd3SJim Ingham         }
63633df7cd3SJim Ingham 
63733df7cd3SJim Ingham         // Options table: Required for subclasses of Options.
63833df7cd3SJim Ingham 
63933df7cd3SJim Ingham         static OptionDefinition g_option_table[];
64033df7cd3SJim Ingham 
64133df7cd3SJim Ingham         // Instance variables to hold the values for command options.
64233df7cd3SJim Ingham         bool m_use_dummy;
64333df7cd3SJim Ingham     };
64433df7cd3SJim Ingham 
6455a988416SJim Ingham protected:
64613d21e9aSBruce Mitchener     bool
64713d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
64830fdc8d8SChris Lattner     {
64933df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
65030fdc8d8SChris Lattner 
651*c8ecc2a9SEugene Zelenko         if (target == nullptr)
65230fdc8d8SChris Lattner         {
65393e0f19fSCaroline Tice             result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
65430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
65530fdc8d8SChris Lattner             return false;
65630fdc8d8SChris Lattner         }
65730fdc8d8SChris Lattner 
65830fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
65930fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
66030fdc8d8SChris Lattner 
66130fdc8d8SChris Lattner         if (num_breakpoints == 0)
66230fdc8d8SChris Lattner         {
66393e0f19fSCaroline Tice             result.AppendError ("No breakpoints exist to have commands deleted");
66430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
66530fdc8d8SChris Lattner             return false;
66630fdc8d8SChris Lattner         }
66730fdc8d8SChris Lattner 
66830fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
66930fdc8d8SChris Lattner         {
67093e0f19fSCaroline Tice             result.AppendError ("No breakpoint specified from which to delete the commands");
67130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
67230fdc8d8SChris Lattner             return false;
67330fdc8d8SChris Lattner         }
67430fdc8d8SChris Lattner 
67530fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
6765e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
67730fdc8d8SChris Lattner 
67830fdc8d8SChris Lattner         if (result.Succeeded())
67930fdc8d8SChris Lattner         {
680c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
681c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
68230fdc8d8SChris Lattner             {
68330fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
68430fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
68530fdc8d8SChris Lattner                 {
68630fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
68730fdc8d8SChris Lattner                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
68830fdc8d8SChris Lattner                     {
68930fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
69030fdc8d8SChris Lattner                         if (bp_loc_sp)
69130fdc8d8SChris Lattner                             bp_loc_sp->ClearCallback();
69230fdc8d8SChris Lattner                         else
69330fdc8d8SChris Lattner                         {
69430fdc8d8SChris Lattner                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
69530fdc8d8SChris Lattner                                                          cur_bp_id.GetBreakpointID(),
69630fdc8d8SChris Lattner                                                          cur_bp_id.GetLocationID());
69730fdc8d8SChris Lattner                             result.SetStatus (eReturnStatusFailed);
69830fdc8d8SChris Lattner                             return false;
69930fdc8d8SChris Lattner                         }
70030fdc8d8SChris Lattner                     }
70130fdc8d8SChris Lattner                     else
70230fdc8d8SChris Lattner                     {
70330fdc8d8SChris Lattner                         bp->ClearCallback();
70430fdc8d8SChris Lattner                     }
70530fdc8d8SChris Lattner                 }
70630fdc8d8SChris Lattner             }
70730fdc8d8SChris Lattner         }
70830fdc8d8SChris Lattner         return result.Succeeded();
70930fdc8d8SChris Lattner     }
710*c8ecc2a9SEugene Zelenko 
71133df7cd3SJim Ingham private:
71233df7cd3SJim Ingham     CommandOptions m_options;
7135a988416SJim Ingham };
71430fdc8d8SChris Lattner 
71533df7cd3SJim Ingham OptionDefinition
71633df7cd3SJim Ingham CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
71733df7cd3SJim Ingham {
718*c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
71933df7cd3SJim Ingham         "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
72033df7cd3SJim Ingham 
721*c8ecc2a9SEugene Zelenko     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
72233df7cd3SJim Ingham };
72333df7cd3SJim Ingham 
72430fdc8d8SChris Lattner //-------------------------------------------------------------------------
72530fdc8d8SChris Lattner // CommandObjectBreakpointCommandList
72630fdc8d8SChris Lattner //-------------------------------------------------------------------------
72730fdc8d8SChris Lattner 
7285a988416SJim Ingham class CommandObjectBreakpointCommandList : public CommandObjectParsed
7295a988416SJim Ingham {
7305a988416SJim Ingham public:
7315a988416SJim Ingham     CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
7325a988416SJim Ingham         CommandObjectParsed(interpreter,
733a7015092SGreg Clayton                             "list",
73430fdc8d8SChris Lattner                             "List the script or set of commands to be executed when the breakpoint is hit.",
735*c8ecc2a9SEugene Zelenko                             nullptr)
73630fdc8d8SChris Lattner     {
737405fe67fSCaroline Tice         CommandArgumentEntry arg;
738405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
739405fe67fSCaroline Tice 
740405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
741405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
742405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
743405fe67fSCaroline Tice 
744405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
745405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
746405fe67fSCaroline Tice 
747405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
748405fe67fSCaroline Tice         m_arguments.push_back (arg);
74930fdc8d8SChris Lattner     }
75030fdc8d8SChris Lattner 
751*c8ecc2a9SEugene Zelenko     ~CommandObjectBreakpointCommandList() override = default;
75230fdc8d8SChris Lattner 
7535a988416SJim Ingham protected:
75413d21e9aSBruce Mitchener     bool
7555a988416SJim Ingham     DoExecute (Args& command,
75613d21e9aSBruce Mitchener              CommandReturnObject &result) override
75730fdc8d8SChris Lattner     {
758a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
75930fdc8d8SChris Lattner 
760*c8ecc2a9SEugene Zelenko         if (target == nullptr)
76130fdc8d8SChris Lattner         {
76230fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
76330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
76430fdc8d8SChris Lattner             return false;
76530fdc8d8SChris Lattner         }
76630fdc8d8SChris Lattner 
76730fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
76830fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
76930fdc8d8SChris Lattner 
77030fdc8d8SChris Lattner         if (num_breakpoints == 0)
77130fdc8d8SChris Lattner         {
77230fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist for which to list commands");
77330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
77430fdc8d8SChris Lattner             return false;
77530fdc8d8SChris Lattner         }
77630fdc8d8SChris Lattner 
77730fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
77830fdc8d8SChris Lattner         {
77930fdc8d8SChris Lattner             result.AppendError ("No breakpoint specified for which to list the commands");
78030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
78130fdc8d8SChris Lattner             return false;
78230fdc8d8SChris Lattner         }
78330fdc8d8SChris Lattner 
78430fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
7855e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
78630fdc8d8SChris Lattner 
78730fdc8d8SChris Lattner         if (result.Succeeded())
78830fdc8d8SChris Lattner         {
789c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
790c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
79130fdc8d8SChris Lattner             {
79230fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
79330fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
79430fdc8d8SChris Lattner                 {
79530fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
79630fdc8d8SChris Lattner 
79730fdc8d8SChris Lattner                     if (bp)
79830fdc8d8SChris Lattner                     {
799*c8ecc2a9SEugene Zelenko                         const BreakpointOptions *bp_options = nullptr;
80030fdc8d8SChris Lattner                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
80130fdc8d8SChris Lattner                         {
80230fdc8d8SChris Lattner                             BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
80330fdc8d8SChris Lattner                             if (bp_loc_sp)
80405407f6bSJim Ingham                                 bp_options = bp_loc_sp->GetOptionsNoCreate();
80530fdc8d8SChris Lattner                             else
80630fdc8d8SChris Lattner                             {
80730fdc8d8SChris Lattner                                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
80830fdc8d8SChris Lattner                                                              cur_bp_id.GetBreakpointID(),
80930fdc8d8SChris Lattner                                                              cur_bp_id.GetLocationID());
81030fdc8d8SChris Lattner                                 result.SetStatus (eReturnStatusFailed);
81130fdc8d8SChris Lattner                                 return false;
81230fdc8d8SChris Lattner                             }
81330fdc8d8SChris Lattner                         }
81430fdc8d8SChris Lattner                         else
81530fdc8d8SChris Lattner                         {
81630fdc8d8SChris Lattner                             bp_options = bp->GetOptions();
81730fdc8d8SChris Lattner                         }
81830fdc8d8SChris Lattner 
81930fdc8d8SChris Lattner                         if (bp_options)
82030fdc8d8SChris Lattner                         {
82130fdc8d8SChris Lattner                             StreamString id_str;
822e16c50a1SJim Ingham                             BreakpointID::GetCanonicalReference (&id_str,
823e16c50a1SJim Ingham                                                                  cur_bp_id.GetBreakpointID(),
824e16c50a1SJim Ingham                                                                  cur_bp_id.GetLocationID());
8251b54c88cSJim Ingham                             const Baton *baton = bp_options->GetBaton();
82630fdc8d8SChris Lattner                             if (baton)
82730fdc8d8SChris Lattner                             {
82830fdc8d8SChris Lattner                                 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
82930fdc8d8SChris Lattner                                 result.GetOutputStream().IndentMore ();
83030fdc8d8SChris Lattner                                 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
83130fdc8d8SChris Lattner                                 result.GetOutputStream().IndentLess ();
83230fdc8d8SChris Lattner                             }
83330fdc8d8SChris Lattner                             else
83430fdc8d8SChris Lattner                             {
835e16c50a1SJim Ingham                                 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
836e16c50a1SJim Ingham                                                                 id_str.GetData());
83730fdc8d8SChris Lattner                             }
83830fdc8d8SChris Lattner                         }
83930fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishResult);
84030fdc8d8SChris Lattner                     }
84130fdc8d8SChris Lattner                     else
84230fdc8d8SChris Lattner                     {
84330fdc8d8SChris Lattner                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
84430fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusFailed);
84530fdc8d8SChris Lattner                     }
84630fdc8d8SChris Lattner                 }
84730fdc8d8SChris Lattner             }
84830fdc8d8SChris Lattner         }
84930fdc8d8SChris Lattner 
85030fdc8d8SChris Lattner         return result.Succeeded();
85130fdc8d8SChris Lattner     }
8525a988416SJim Ingham };
85330fdc8d8SChris Lattner 
85430fdc8d8SChris Lattner //-------------------------------------------------------------------------
85530fdc8d8SChris Lattner // CommandObjectBreakpointCommand
85630fdc8d8SChris Lattner //-------------------------------------------------------------------------
85730fdc8d8SChris Lattner 
8586611103cSGreg Clayton CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
859a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
860a7015092SGreg Clayton                             "command",
8617050e0b1SSean Callanan                             "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
86230fdc8d8SChris Lattner                             "command <sub-command> [<sub-command-options>] <breakpoint-id>")
86330fdc8d8SChris Lattner {
864a7015092SGreg Clayton     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
86593e0f19fSCaroline Tice     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
866a7015092SGreg Clayton     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
86730fdc8d8SChris Lattner 
86830fdc8d8SChris Lattner     add_command_object->SetCommandName ("breakpoint command add");
86993e0f19fSCaroline Tice     delete_command_object->SetCommandName ("breakpoint command delete");
87030fdc8d8SChris Lattner     list_command_object->SetCommandName ("breakpoint command list");
87130fdc8d8SChris Lattner 
87223f59509SGreg Clayton     LoadSubCommand ("add",    add_command_object);
87323f59509SGreg Clayton     LoadSubCommand ("delete", delete_command_object);
87423f59509SGreg Clayton     LoadSubCommand ("list",   list_command_object);
87530fdc8d8SChris Lattner }
87630fdc8d8SChris Lattner 
877*c8ecc2a9SEugene Zelenko CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand() = default;
878