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:
39*7428a18cSKate Stone     CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter)
40*7428a18cSKate Stone         : CommandObjectParsed(interpreter, "add",
41*7428a18cSKate 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),
45eb0103f2SGreg Clayton           m_options(interpreter)
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:
2985a988416SJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
2995a988416SJim Ingham             Options (interpreter),
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
31213d21e9aSBruce Mitchener         SetOptionValue (uint32_t option_idx, const char *option_arg) override
3135a988416SJim Ingham         {
3145a988416SJim Ingham             Error error;
3153bcdfc0eSGreg Clayton             const int short_option = m_getopt_table[option_idx].val;
3165a988416SJim Ingham 
3175a988416SJim Ingham             switch (short_option)
3185a988416SJim Ingham             {
3195a988416SJim Ingham             case 'o':
3205a988416SJim Ingham                 m_use_one_liner = true;
3215a988416SJim Ingham                 m_one_liner = option_arg;
3225a988416SJim Ingham                 break;
3235a988416SJim Ingham 
3245a988416SJim Ingham             case 's':
3255a988416SJim Ingham                 m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
3265a988416SJim Ingham                                                                                      g_option_table[option_idx].enum_values,
3275a988416SJim Ingham                                                                                      eScriptLanguageNone,
3285a988416SJim Ingham                                                                                      error);
3295a988416SJim Ingham 
3305a988416SJim Ingham                 if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
3315a988416SJim Ingham                 {
3325a988416SJim Ingham                     m_use_script_language = true;
3335a988416SJim Ingham                 }
3345a988416SJim Ingham                 else
3355a988416SJim Ingham                 {
3365a988416SJim Ingham                     m_use_script_language = false;
3375a988416SJim Ingham                 }
3385a988416SJim Ingham                 break;
3395a988416SJim Ingham 
3405a988416SJim Ingham             case 'e':
3415a988416SJim Ingham                 {
3425a988416SJim Ingham                     bool success = false;
3435a988416SJim Ingham                     m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
3445a988416SJim Ingham                     if (!success)
3455a988416SJim Ingham                         error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
3465a988416SJim Ingham                 }
3475a988416SJim Ingham                 break;
3485a988416SJim Ingham 
3495a988416SJim Ingham             case 'F':
3505a988416SJim Ingham                 m_use_one_liner = false;
3515a988416SJim Ingham                 m_use_script_language = true;
3525a988416SJim Ingham                 m_function_name.assign(option_arg);
3535a988416SJim Ingham                 break;
3545a988416SJim Ingham 
35533df7cd3SJim Ingham             case 'D':
35633df7cd3SJim Ingham                 m_use_dummy = true;
35733df7cd3SJim Ingham                 break;
35833df7cd3SJim Ingham 
3595a988416SJim Ingham             default:
3605a988416SJim Ingham                 break;
3615a988416SJim Ingham             }
3625a988416SJim Ingham             return error;
3635a988416SJim Ingham         }
364c8ecc2a9SEugene Zelenko 
3655a988416SJim Ingham         void
36613d21e9aSBruce Mitchener         OptionParsingStarting () override
3675a988416SJim Ingham         {
3685a988416SJim Ingham             m_use_commands = true;
3695a988416SJim Ingham             m_use_script_language = false;
3705a988416SJim Ingham             m_script_language = eScriptLanguageNone;
3715a988416SJim Ingham 
3725a988416SJim Ingham             m_use_one_liner = false;
3735a988416SJim Ingham             m_stop_on_error = true;
3745a988416SJim Ingham             m_one_liner.clear();
3755a988416SJim Ingham             m_function_name.clear();
37633df7cd3SJim Ingham             m_use_dummy = false;
3775a988416SJim Ingham         }
3785a988416SJim Ingham 
3795a988416SJim Ingham         const OptionDefinition*
38013d21e9aSBruce Mitchener         GetDefinitions () override
3815a988416SJim Ingham         {
3825a988416SJim Ingham             return g_option_table;
3835a988416SJim Ingham         }
3845a988416SJim Ingham 
3855a988416SJim Ingham         // Options table: Required for subclasses of Options.
3865a988416SJim Ingham 
3875a988416SJim Ingham         static OptionDefinition g_option_table[];
3885a988416SJim Ingham 
3895a988416SJim Ingham         // Instance variables to hold the values for command options.
3905a988416SJim Ingham 
3915a988416SJim Ingham         bool m_use_commands;
3925a988416SJim Ingham         bool m_use_script_language;
3935a988416SJim Ingham         lldb::ScriptLanguage m_script_language;
3945a988416SJim Ingham 
3955a988416SJim Ingham         // Instance variables to hold the values for one_liner options.
3965a988416SJim Ingham         bool m_use_one_liner;
3975a988416SJim Ingham         std::string m_one_liner;
3985a988416SJim Ingham         bool m_stop_on_error;
3995a988416SJim Ingham         std::string m_function_name;
40033df7cd3SJim Ingham         bool m_use_dummy;
4015a988416SJim Ingham     };
4025a988416SJim Ingham 
4035a988416SJim Ingham protected:
40413d21e9aSBruce Mitchener     bool
40513d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
40630fdc8d8SChris Lattner     {
40733df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
40830fdc8d8SChris Lattner 
409c8ecc2a9SEugene Zelenko         if (target == nullptr)
41030fdc8d8SChris Lattner         {
41130fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
41230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
41330fdc8d8SChris Lattner             return false;
41430fdc8d8SChris Lattner         }
41530fdc8d8SChris Lattner 
41630fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
41730fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
41830fdc8d8SChris Lattner 
41930fdc8d8SChris Lattner         if (num_breakpoints == 0)
42030fdc8d8SChris Lattner         {
42130fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist to have commands added");
42230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
42330fdc8d8SChris Lattner             return false;
42430fdc8d8SChris Lattner         }
42530fdc8d8SChris Lattner 
426c8ecc2a9SEugene Zelenko         if (!m_options.m_use_script_language && !m_options.m_function_name.empty())
4278d4a8010SEnrico Granata         {
4288d4a8010SEnrico Granata             result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
4298d4a8010SEnrico Granata             result.SetStatus (eReturnStatusFailed);
4308d4a8010SEnrico Granata             return false;
4318d4a8010SEnrico Granata         }
4328d4a8010SEnrico Granata 
43330fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
4345e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
43530fdc8d8SChris Lattner 
436b5796cb4SJim Ingham         m_bp_options_vec.clear();
437b5796cb4SJim Ingham 
43830fdc8d8SChris Lattner         if (result.Succeeded())
43930fdc8d8SChris Lattner         {
440c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
441d9916eaeSJim Ingham 
442c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
44330fdc8d8SChris Lattner             {
44430fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
44530fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
44630fdc8d8SChris Lattner                 {
44730fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
448c8ecc2a9SEugene Zelenko                     BreakpointOptions *bp_options = nullptr;
44939d7d4f0SJohnny Chen                     if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
45039d7d4f0SJohnny Chen                     {
45139d7d4f0SJohnny Chen                         // This breakpoint does not have an associated location.
45239d7d4f0SJohnny Chen                         bp_options = bp->GetOptions();
45339d7d4f0SJohnny Chen                     }
45439d7d4f0SJohnny Chen                     else
45530fdc8d8SChris Lattner                     {
45630fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
45739d7d4f0SJohnny Chen                         // This breakpoint does have an associated location.
45839d7d4f0SJohnny Chen                         // Get its breakpoint options.
45930fdc8d8SChris Lattner                         if (bp_loc_sp)
46039d7d4f0SJohnny Chen                             bp_options = bp_loc_sp->GetLocationOptions();
46139d7d4f0SJohnny Chen                     }
462b5796cb4SJim Ingham                     if (bp_options)
463b5796cb4SJim Ingham                         m_bp_options_vec.push_back (bp_options);
464b5796cb4SJim Ingham                 }
465b5796cb4SJim Ingham             }
46639d7d4f0SJohnny Chen 
46739d7d4f0SJohnny Chen             // If we are using script language, get the script interpreter
46839d7d4f0SJohnny Chen             // in order to set or collect command callback.  Otherwise, call
46939d7d4f0SJohnny Chen             // the methods associated with this object.
47030fdc8d8SChris Lattner             if (m_options.m_use_script_language)
47130fdc8d8SChris Lattner             {
472b5796cb4SJim Ingham                 ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
47339d7d4f0SJohnny Chen                 // Special handling for one-liner specified inline.
47439d7d4f0SJohnny Chen                 if (m_options.m_use_one_liner)
4758d4a8010SEnrico Granata                 {
476b5796cb4SJim Ingham                     script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
47739d7d4f0SJohnny Chen                                                                  m_options.m_one_liner.c_str());
4788d4a8010SEnrico Granata                 }
479c8ecc2a9SEugene Zelenko                 else if (!m_options.m_function_name.empty())
4808d4a8010SEnrico Granata                 {
481b5796cb4SJim Ingham                     script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
482d80102e4SJim Ingham                                                                          m_options.m_function_name.c_str());
4838d4a8010SEnrico Granata                 }
48494de55d5SJohnny Chen                 else
4858d4a8010SEnrico Granata                 {
486b5796cb4SJim Ingham                     script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
48730fdc8d8SChris Lattner                                                                             result);
48830fdc8d8SChris Lattner                 }
4898d4a8010SEnrico Granata             }
49030fdc8d8SChris Lattner             else
49130fdc8d8SChris Lattner             {
49239d7d4f0SJohnny Chen                 // Special handling for one-liner specified inline.
49339d7d4f0SJohnny Chen                 if (m_options.m_use_one_liner)
494b5796cb4SJim Ingham                     SetBreakpointCommandCallback (m_bp_options_vec,
49539d7d4f0SJohnny Chen                                                   m_options.m_one_liner.c_str());
49639d7d4f0SJohnny Chen                 else
497b5796cb4SJim Ingham                     CollectDataForBreakpointCommandCallback (m_bp_options_vec,
498b132097bSGreg Clayton                                                              result);
49930fdc8d8SChris Lattner             }
50030fdc8d8SChris Lattner         }
50130fdc8d8SChris Lattner 
50230fdc8d8SChris Lattner         return result.Succeeded();
50330fdc8d8SChris Lattner     }
50430fdc8d8SChris Lattner 
5055a988416SJim Ingham private:
5065a988416SJim Ingham     CommandOptions m_options;
507b5796cb4SJim Ingham     std::vector<BreakpointOptions *> m_bp_options_vec;  // This stores the breakpoint options that we are currently
508b5796cb4SJim Ingham                                                         // collecting commands for.  In the CollectData... calls we need
509b5796cb4SJim Ingham                                                         // to hand this off to the IOHandler, which may run asynchronously.
510b5796cb4SJim Ingham                                                         // So we have to have some way to keep it alive, and not leak it.
511b5796cb4SJim Ingham                                                         // Making it an ivar of the command object, which never goes away
512b5796cb4SJim Ingham                                                         // achieves this.  Note that if we were able to run
513b5796cb4SJim Ingham                                                         // the same command concurrently in one interpreter we'd have to
514b5796cb4SJim Ingham                                                         // make this "per invocation".  But there are many more reasons
515b5796cb4SJim Ingham                                                         // why it is not in general safe to do that in lldb at present,
516b5796cb4SJim Ingham                                                         // so it isn't worthwhile to come up with a more complex mechanism
517b5796cb4SJim Ingham                                                         // to address this particular weakness right now.
5185a988416SJim Ingham     static const char *g_reader_instructions;
5195a988416SJim Ingham };
5205a988416SJim Ingham 
5215a988416SJim Ingham const char *
52244d93782SGreg Clayton CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s).  Type 'DONE' to end.\n";
5235a988416SJim Ingham 
5245a988416SJim Ingham // FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
5255a988416SJim Ingham // language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
5265a988416SJim Ingham 
5275a988416SJim Ingham static OptionEnumValueElement
5285a988416SJim Ingham g_script_option_enumeration[4] =
52930fdc8d8SChris Lattner {
5305a988416SJim Ingham     { eScriptLanguageNone,    "command",         "Commands are in the lldb command interpreter language"},
5315a988416SJim Ingham     { eScriptLanguagePython,  "python",          "Commands are in the Python language."},
5325a988416SJim Ingham     { eSortOrderByName,       "default-script",  "Commands are in the default scripting language."},
533c8ecc2a9SEugene Zelenko     { 0,                      nullptr,           nullptr }
5345a988416SJim Ingham };
53530fdc8d8SChris Lattner 
5365a988416SJim Ingham OptionDefinition
5375a988416SJim Ingham CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
53830fdc8d8SChris Lattner {
539c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeOneLiner,
5405a988416SJim Ingham         "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
54130fdc8d8SChris Lattner 
542c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,
5435a988416SJim Ingham         "Specify whether breakpoint command execution should terminate on error." },
54430fdc8d8SChris Lattner 
545c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_ALL,   false, "script-type",     's', OptionParser::eRequiredArgument, nullptr, g_script_option_enumeration, 0, eArgTypeNone,
5465a988416SJim Ingham         "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
54730fdc8d8SChris Lattner 
548c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_2,   false, "python-function",     'F', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePythonFunction,
5495a988416SJim Ingham         "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate."},
55039d7d4f0SJohnny Chen 
551c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
55233df7cd3SJim Ingham         "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
55333df7cd3SJim Ingham 
554c8ecc2a9SEugene Zelenko     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
5555a988416SJim Ingham };
55630fdc8d8SChris Lattner 
55730fdc8d8SChris Lattner //-------------------------------------------------------------------------
55893e0f19fSCaroline Tice // CommandObjectBreakpointCommandDelete
55930fdc8d8SChris Lattner //-------------------------------------------------------------------------
56030fdc8d8SChris Lattner 
5615a988416SJim Ingham class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
5625a988416SJim Ingham {
5635a988416SJim Ingham public:
5645a988416SJim Ingham     CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
5655a988416SJim Ingham         CommandObjectParsed(interpreter,
56693e0f19fSCaroline Tice                             "delete",
56793e0f19fSCaroline Tice                             "Delete the set of commands from a breakpoint.",
568c8ecc2a9SEugene Zelenko                             nullptr),
56933df7cd3SJim Ingham         m_options (interpreter)
57030fdc8d8SChris Lattner     {
571405fe67fSCaroline Tice         CommandArgumentEntry arg;
572405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
573405fe67fSCaroline Tice 
574405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
575405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
576405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
577405fe67fSCaroline Tice 
578405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
579405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
580405fe67fSCaroline Tice 
581405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
582405fe67fSCaroline Tice         m_arguments.push_back (arg);
58330fdc8d8SChris Lattner     }
58430fdc8d8SChris Lattner 
585c8ecc2a9SEugene Zelenko     ~CommandObjectBreakpointCommandDelete() override = default;
5865a988416SJim Ingham 
58713d21e9aSBruce Mitchener     Options *
58813d21e9aSBruce Mitchener     GetOptions () override
58933df7cd3SJim Ingham     {
59033df7cd3SJim Ingham         return &m_options;
59133df7cd3SJim Ingham     }
59233df7cd3SJim Ingham 
59333df7cd3SJim Ingham     class CommandOptions : public Options
59433df7cd3SJim Ingham     {
59533df7cd3SJim Ingham     public:
59633df7cd3SJim Ingham         CommandOptions (CommandInterpreter &interpreter) :
59733df7cd3SJim Ingham             Options (interpreter),
59833df7cd3SJim Ingham             m_use_dummy (false)
59933df7cd3SJim Ingham         {
60033df7cd3SJim Ingham         }
60133df7cd3SJim Ingham 
602c8ecc2a9SEugene Zelenko         ~CommandOptions() override = default;
60333df7cd3SJim Ingham 
60413d21e9aSBruce Mitchener         Error
60513d21e9aSBruce Mitchener         SetOptionValue (uint32_t option_idx, const char *option_arg) override
60633df7cd3SJim Ingham         {
60733df7cd3SJim Ingham             Error error;
60833df7cd3SJim Ingham             const int short_option = m_getopt_table[option_idx].val;
60933df7cd3SJim Ingham 
61033df7cd3SJim Ingham             switch (short_option)
61133df7cd3SJim Ingham             {
61233df7cd3SJim Ingham                 case 'D':
61333df7cd3SJim Ingham                     m_use_dummy = true;
61433df7cd3SJim Ingham                     break;
61533df7cd3SJim Ingham 
61633df7cd3SJim Ingham                 default:
61733df7cd3SJim Ingham                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
61833df7cd3SJim Ingham                     break;
61933df7cd3SJim Ingham             }
62033df7cd3SJim Ingham 
62133df7cd3SJim Ingham             return error;
62233df7cd3SJim Ingham         }
62333df7cd3SJim Ingham 
62433df7cd3SJim Ingham         void
62513d21e9aSBruce Mitchener         OptionParsingStarting () override
62633df7cd3SJim Ingham         {
62733df7cd3SJim Ingham             m_use_dummy = false;
62833df7cd3SJim Ingham         }
62933df7cd3SJim Ingham 
63033df7cd3SJim Ingham         const OptionDefinition*
63113d21e9aSBruce Mitchener         GetDefinitions () override
63233df7cd3SJim Ingham         {
63333df7cd3SJim Ingham             return g_option_table;
63433df7cd3SJim Ingham         }
63533df7cd3SJim Ingham 
63633df7cd3SJim Ingham         // Options table: Required for subclasses of Options.
63733df7cd3SJim Ingham 
63833df7cd3SJim Ingham         static OptionDefinition g_option_table[];
63933df7cd3SJim Ingham 
64033df7cd3SJim Ingham         // Instance variables to hold the values for command options.
64133df7cd3SJim Ingham         bool m_use_dummy;
64233df7cd3SJim Ingham     };
64333df7cd3SJim Ingham 
6445a988416SJim Ingham protected:
64513d21e9aSBruce Mitchener     bool
64613d21e9aSBruce Mitchener     DoExecute (Args& command, CommandReturnObject &result) override
64730fdc8d8SChris Lattner     {
64833df7cd3SJim Ingham         Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
64930fdc8d8SChris Lattner 
650c8ecc2a9SEugene Zelenko         if (target == nullptr)
65130fdc8d8SChris Lattner         {
65293e0f19fSCaroline Tice             result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
65330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
65430fdc8d8SChris Lattner             return false;
65530fdc8d8SChris Lattner         }
65630fdc8d8SChris Lattner 
65730fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
65830fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
65930fdc8d8SChris Lattner 
66030fdc8d8SChris Lattner         if (num_breakpoints == 0)
66130fdc8d8SChris Lattner         {
66293e0f19fSCaroline Tice             result.AppendError ("No breakpoints exist to have commands deleted");
66330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
66430fdc8d8SChris Lattner             return false;
66530fdc8d8SChris Lattner         }
66630fdc8d8SChris Lattner 
66730fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
66830fdc8d8SChris Lattner         {
66993e0f19fSCaroline Tice             result.AppendError ("No breakpoint specified from which to delete the commands");
67030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
67130fdc8d8SChris Lattner             return false;
67230fdc8d8SChris Lattner         }
67330fdc8d8SChris Lattner 
67430fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
6755e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
67630fdc8d8SChris Lattner 
67730fdc8d8SChris Lattner         if (result.Succeeded())
67830fdc8d8SChris Lattner         {
679c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
680c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
68130fdc8d8SChris Lattner             {
68230fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
68330fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
68430fdc8d8SChris Lattner                 {
68530fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
68630fdc8d8SChris Lattner                     if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
68730fdc8d8SChris Lattner                     {
68830fdc8d8SChris Lattner                         BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
68930fdc8d8SChris Lattner                         if (bp_loc_sp)
69030fdc8d8SChris Lattner                             bp_loc_sp->ClearCallback();
69130fdc8d8SChris Lattner                         else
69230fdc8d8SChris Lattner                         {
69330fdc8d8SChris Lattner                             result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
69430fdc8d8SChris Lattner                                                          cur_bp_id.GetBreakpointID(),
69530fdc8d8SChris Lattner                                                          cur_bp_id.GetLocationID());
69630fdc8d8SChris Lattner                             result.SetStatus (eReturnStatusFailed);
69730fdc8d8SChris Lattner                             return false;
69830fdc8d8SChris Lattner                         }
69930fdc8d8SChris Lattner                     }
70030fdc8d8SChris Lattner                     else
70130fdc8d8SChris Lattner                     {
70230fdc8d8SChris Lattner                         bp->ClearCallback();
70330fdc8d8SChris Lattner                     }
70430fdc8d8SChris Lattner                 }
70530fdc8d8SChris Lattner             }
70630fdc8d8SChris Lattner         }
70730fdc8d8SChris Lattner         return result.Succeeded();
70830fdc8d8SChris Lattner     }
709c8ecc2a9SEugene Zelenko 
71033df7cd3SJim Ingham private:
71133df7cd3SJim Ingham     CommandOptions m_options;
7125a988416SJim Ingham };
71330fdc8d8SChris Lattner 
71433df7cd3SJim Ingham OptionDefinition
71533df7cd3SJim Ingham CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
71633df7cd3SJim Ingham {
717c8ecc2a9SEugene Zelenko     { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone,
71833df7cd3SJim Ingham         "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
71933df7cd3SJim Ingham 
720c8ecc2a9SEugene Zelenko     { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr }
72133df7cd3SJim Ingham };
72233df7cd3SJim Ingham 
72330fdc8d8SChris Lattner //-------------------------------------------------------------------------
72430fdc8d8SChris Lattner // CommandObjectBreakpointCommandList
72530fdc8d8SChris Lattner //-------------------------------------------------------------------------
72630fdc8d8SChris Lattner 
7275a988416SJim Ingham class CommandObjectBreakpointCommandList : public CommandObjectParsed
7285a988416SJim Ingham {
7295a988416SJim Ingham public:
7305a988416SJim Ingham     CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
7315a988416SJim Ingham         CommandObjectParsed(interpreter,
732a7015092SGreg Clayton                             "list",
73330fdc8d8SChris Lattner                             "List the script or set of commands to be executed when the breakpoint is hit.",
734c8ecc2a9SEugene Zelenko                             nullptr)
73530fdc8d8SChris Lattner     {
736405fe67fSCaroline Tice         CommandArgumentEntry arg;
737405fe67fSCaroline Tice         CommandArgumentData bp_id_arg;
738405fe67fSCaroline Tice 
739405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
740405fe67fSCaroline Tice         bp_id_arg.arg_type = eArgTypeBreakpointID;
741405fe67fSCaroline Tice         bp_id_arg.arg_repetition = eArgRepeatPlain;
742405fe67fSCaroline Tice 
743405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
744405fe67fSCaroline Tice         arg.push_back (bp_id_arg);
745405fe67fSCaroline Tice 
746405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
747405fe67fSCaroline Tice         m_arguments.push_back (arg);
74830fdc8d8SChris Lattner     }
74930fdc8d8SChris Lattner 
750c8ecc2a9SEugene Zelenko     ~CommandObjectBreakpointCommandList() override = default;
75130fdc8d8SChris Lattner 
7525a988416SJim Ingham protected:
75313d21e9aSBruce Mitchener     bool
7545a988416SJim Ingham     DoExecute (Args& command,
75513d21e9aSBruce Mitchener              CommandReturnObject &result) override
75630fdc8d8SChris Lattner     {
757a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
75830fdc8d8SChris Lattner 
759c8ecc2a9SEugene Zelenko         if (target == nullptr)
76030fdc8d8SChris Lattner         {
76130fdc8d8SChris Lattner             result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
76230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
76330fdc8d8SChris Lattner             return false;
76430fdc8d8SChris Lattner         }
76530fdc8d8SChris Lattner 
76630fdc8d8SChris Lattner         const BreakpointList &breakpoints = target->GetBreakpointList();
76730fdc8d8SChris Lattner         size_t num_breakpoints = breakpoints.GetSize();
76830fdc8d8SChris Lattner 
76930fdc8d8SChris Lattner         if (num_breakpoints == 0)
77030fdc8d8SChris Lattner         {
77130fdc8d8SChris Lattner             result.AppendError ("No breakpoints exist for which to list commands");
77230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
77330fdc8d8SChris Lattner             return false;
77430fdc8d8SChris Lattner         }
77530fdc8d8SChris Lattner 
77630fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
77730fdc8d8SChris Lattner         {
77830fdc8d8SChris Lattner             result.AppendError ("No breakpoint specified for which to list the commands");
77930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
78030fdc8d8SChris Lattner             return false;
78130fdc8d8SChris Lattner         }
78230fdc8d8SChris Lattner 
78330fdc8d8SChris Lattner         BreakpointIDList valid_bp_ids;
7845e09c8c3SJim Ingham         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
78530fdc8d8SChris Lattner 
78630fdc8d8SChris Lattner         if (result.Succeeded())
78730fdc8d8SChris Lattner         {
788c982c768SGreg Clayton             const size_t count = valid_bp_ids.GetSize();
789c982c768SGreg Clayton             for (size_t i = 0; i < count; ++i)
79030fdc8d8SChris Lattner             {
79130fdc8d8SChris Lattner                 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
79230fdc8d8SChris Lattner                 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
79330fdc8d8SChris Lattner                 {
79430fdc8d8SChris Lattner                     Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
79530fdc8d8SChris Lattner 
79630fdc8d8SChris Lattner                     if (bp)
79730fdc8d8SChris Lattner                     {
798c8ecc2a9SEugene Zelenko                         const BreakpointOptions *bp_options = nullptr;
79930fdc8d8SChris Lattner                         if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
80030fdc8d8SChris Lattner                         {
80130fdc8d8SChris Lattner                             BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
80230fdc8d8SChris Lattner                             if (bp_loc_sp)
80305407f6bSJim Ingham                                 bp_options = bp_loc_sp->GetOptionsNoCreate();
80430fdc8d8SChris Lattner                             else
80530fdc8d8SChris Lattner                             {
80630fdc8d8SChris Lattner                                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
80730fdc8d8SChris Lattner                                                              cur_bp_id.GetBreakpointID(),
80830fdc8d8SChris Lattner                                                              cur_bp_id.GetLocationID());
80930fdc8d8SChris Lattner                                 result.SetStatus (eReturnStatusFailed);
81030fdc8d8SChris Lattner                                 return false;
81130fdc8d8SChris Lattner                             }
81230fdc8d8SChris Lattner                         }
81330fdc8d8SChris Lattner                         else
81430fdc8d8SChris Lattner                         {
81530fdc8d8SChris Lattner                             bp_options = bp->GetOptions();
81630fdc8d8SChris Lattner                         }
81730fdc8d8SChris Lattner 
81830fdc8d8SChris Lattner                         if (bp_options)
81930fdc8d8SChris Lattner                         {
82030fdc8d8SChris Lattner                             StreamString id_str;
821e16c50a1SJim Ingham                             BreakpointID::GetCanonicalReference (&id_str,
822e16c50a1SJim Ingham                                                                  cur_bp_id.GetBreakpointID(),
823e16c50a1SJim Ingham                                                                  cur_bp_id.GetLocationID());
8241b54c88cSJim Ingham                             const Baton *baton = bp_options->GetBaton();
82530fdc8d8SChris Lattner                             if (baton)
82630fdc8d8SChris Lattner                             {
82730fdc8d8SChris Lattner                                 result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
82830fdc8d8SChris Lattner                                 result.GetOutputStream().IndentMore ();
82930fdc8d8SChris Lattner                                 baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
83030fdc8d8SChris Lattner                                 result.GetOutputStream().IndentLess ();
83130fdc8d8SChris Lattner                             }
83230fdc8d8SChris Lattner                             else
83330fdc8d8SChris Lattner                             {
834e16c50a1SJim Ingham                                 result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
835e16c50a1SJim Ingham                                                                 id_str.GetData());
83630fdc8d8SChris Lattner                             }
83730fdc8d8SChris Lattner                         }
83830fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishResult);
83930fdc8d8SChris Lattner                     }
84030fdc8d8SChris Lattner                     else
84130fdc8d8SChris Lattner                     {
84230fdc8d8SChris Lattner                         result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
84330fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusFailed);
84430fdc8d8SChris Lattner                     }
84530fdc8d8SChris Lattner                 }
84630fdc8d8SChris Lattner             }
84730fdc8d8SChris Lattner         }
84830fdc8d8SChris Lattner 
84930fdc8d8SChris Lattner         return result.Succeeded();
85030fdc8d8SChris Lattner     }
8515a988416SJim Ingham };
85230fdc8d8SChris Lattner 
85330fdc8d8SChris Lattner //-------------------------------------------------------------------------
85430fdc8d8SChris Lattner // CommandObjectBreakpointCommand
85530fdc8d8SChris Lattner //-------------------------------------------------------------------------
85630fdc8d8SChris Lattner 
857*7428a18cSKate Stone CommandObjectBreakpointCommand::CommandObjectBreakpointCommand(CommandInterpreter &interpreter)
858*7428a18cSKate Stone     : CommandObjectMultiword(
859*7428a18cSKate Stone           interpreter, "command",
860*7428a18cSKate Stone           "Commands for adding, removing and listing LLDB commands executed when a breakpoint is hit.",
86130fdc8d8SChris Lattner           "command <sub-command> [<sub-command-options>] <breakpoint-id>")
86230fdc8d8SChris Lattner {
863a7015092SGreg Clayton     CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
86493e0f19fSCaroline Tice     CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
865a7015092SGreg Clayton     CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
86630fdc8d8SChris Lattner 
86730fdc8d8SChris Lattner     add_command_object->SetCommandName ("breakpoint command add");
86893e0f19fSCaroline Tice     delete_command_object->SetCommandName ("breakpoint command delete");
86930fdc8d8SChris Lattner     list_command_object->SetCommandName ("breakpoint command list");
87030fdc8d8SChris Lattner 
87123f59509SGreg Clayton     LoadSubCommand ("add",    add_command_object);
87223f59509SGreg Clayton     LoadSubCommand ("delete", delete_command_object);
87323f59509SGreg Clayton     LoadSubCommand ("list",   list_command_object);
87430fdc8d8SChris Lattner }
87530fdc8d8SChris Lattner 
876c8ecc2a9SEugene Zelenko CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand() = default;
877