1ac7ddfbfSEd Maste //===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "CommandObjectBreakpointCommand.h"
11ac7ddfbfSEd Maste #include "CommandObjectBreakpoint.h"
12435933ddSDimitry Andric #include "lldb/Breakpoint/Breakpoint.h"
13435933ddSDimitry Andric #include "lldb/Breakpoint/BreakpointIDList.h"
14435933ddSDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h"
15435933ddSDimitry Andric #include "lldb/Breakpoint/StoppointCallbackContext.h"
1612b93ac6SEd Maste #include "lldb/Core/IOHandler.h"
17f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h"
18ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
19ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
204ba319b5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
21ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
22ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
23*b5893f02SDimitry Andric #include "lldb/Utility/State.h"
24435933ddSDimitry Andric 
25435933ddSDimitry Andric #include "llvm/ADT/STLExtras.h"
26ac7ddfbfSEd Maste 
27ac7ddfbfSEd Maste using namespace lldb;
28ac7ddfbfSEd Maste using namespace lldb_private;
29ac7ddfbfSEd Maste 
30ac7ddfbfSEd Maste //-------------------------------------------------------------------------
31ac7ddfbfSEd Maste // CommandObjectBreakpointCommandAdd
32ac7ddfbfSEd Maste //-------------------------------------------------------------------------
33ac7ddfbfSEd Maste 
34435933ddSDimitry Andric // FIXME: "script-type" needs to have its contents determined dynamically, so
35435933ddSDimitry Andric // somebody can add a new scripting
36435933ddSDimitry Andric // language to lldb and have it pickable here without having to change this
37435933ddSDimitry Andric // enumeration by hand and rebuild lldb proper.
38435933ddSDimitry Andric 
39*b5893f02SDimitry Andric static constexpr OptionEnumValueElement g_script_option_enumeration[] = {
40435933ddSDimitry Andric     {eScriptLanguageNone, "command",
41435933ddSDimitry Andric      "Commands are in the lldb command interpreter language"},
42435933ddSDimitry Andric     {eScriptLanguagePython, "python", "Commands are in the Python language."},
43435933ddSDimitry Andric     {eSortOrderByName, "default-script",
44*b5893f02SDimitry Andric      "Commands are in the default scripting language."} };
45435933ddSDimitry Andric 
ScriptOptionEnum()46*b5893f02SDimitry Andric static constexpr OptionEnumValues ScriptOptionEnum() {
47*b5893f02SDimitry Andric   return OptionEnumValues(g_script_option_enumeration);
48*b5893f02SDimitry Andric }
49*b5893f02SDimitry Andric 
50*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_add_options[] = {
51435933ddSDimitry Andric     // clang-format off
52*b5893f02SDimitry Andric   { LLDB_OPT_SET_1,   false, "one-liner",         'o', OptionParser::eRequiredArgument, nullptr, {},                 0, eArgTypeOneLiner,       "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
53*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "stop-on-error",     'e', OptionParser::eRequiredArgument, nullptr, {},                 0, eArgTypeBoolean,        "Specify whether breakpoint command execution should terminate on error." },
54*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "script-type",       's', OptionParser::eRequiredArgument, nullptr, ScriptOptionEnum(), 0, eArgTypeNone,           "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." },
55*b5893f02SDimitry Andric   { LLDB_OPT_SET_2,   false, "python-function",   'F', OptionParser::eRequiredArgument, nullptr, {},                 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate." },
56*b5893f02SDimitry Andric   { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument,       nullptr, {},                 0, eArgTypeNone,           "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
57435933ddSDimitry Andric     // clang-format on
58435933ddSDimitry Andric };
59435933ddSDimitry Andric 
60435933ddSDimitry Andric class CommandObjectBreakpointCommandAdd : public CommandObjectParsed,
61435933ddSDimitry Andric                                           public IOHandlerDelegateMultiline {
62ac7ddfbfSEd Maste public:
CommandObjectBreakpointCommandAdd(CommandInterpreter & interpreter)634bb0738eSEd Maste   CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter)
644bb0738eSEd Maste       : CommandObjectParsed(interpreter, "add",
65435933ddSDimitry Andric                             "Add LLDB commands to a breakpoint, to be executed "
66435933ddSDimitry Andric                             "whenever the breakpoint is hit."
67435933ddSDimitry Andric                             "  If no breakpoint is specified, adds the "
68435933ddSDimitry Andric                             "commands to the last created breakpoint.",
694bb0738eSEd Maste                             nullptr),
70435933ddSDimitry Andric         IOHandlerDelegateMultiline("DONE",
71435933ddSDimitry Andric                                    IOHandlerDelegate::Completion::LLDBCommand),
72435933ddSDimitry Andric         m_options() {
73ac7ddfbfSEd Maste     SetHelpLong(
74b91a7dfcSDimitry Andric         R"(
75b91a7dfcSDimitry Andric General information about entering breakpoint commands
76b91a7dfcSDimitry Andric ------------------------------------------------------
77b91a7dfcSDimitry Andric 
78435933ddSDimitry Andric )"
79435933ddSDimitry Andric         "This command will prompt for commands to be executed when the specified \
80b91a7dfcSDimitry Andric breakpoint is hit.  Each command is typed on its own line following the '> ' \
81435933ddSDimitry Andric prompt until 'DONE' is entered."
82435933ddSDimitry Andric         R"(
83b91a7dfcSDimitry Andric 
84435933ddSDimitry Andric )"
85435933ddSDimitry Andric         "Syntactic errors may not be detected when initially entered, and many \
86b91a7dfcSDimitry Andric malformed commands can silently fail when executed.  If your breakpoint commands \
87435933ddSDimitry Andric do not appear to be executing, double-check the command syntax."
88435933ddSDimitry Andric         R"(
89b91a7dfcSDimitry Andric 
90435933ddSDimitry Andric )"
91435933ddSDimitry Andric         "Note: You may enter any debugger command exactly as you would at the debugger \
92b91a7dfcSDimitry Andric prompt.  There is no limit to the number of commands supplied, but do NOT enter \
93435933ddSDimitry Andric more than one command per line."
94435933ddSDimitry Andric         R"(
95b91a7dfcSDimitry Andric 
96b91a7dfcSDimitry Andric Special information about PYTHON breakpoint commands
97b91a7dfcSDimitry Andric ----------------------------------------------------
98b91a7dfcSDimitry Andric 
99435933ddSDimitry Andric )"
100435933ddSDimitry Andric         "You may enter either one or more lines of Python, including function \
101b91a7dfcSDimitry Andric definitions or calls to functions that will have been imported by the time \
102b91a7dfcSDimitry Andric the code executes.  Single line breakpoint commands will be interpreted 'as is' \
103b91a7dfcSDimitry Andric when the breakpoint is hit.  Multiple lines of Python will be wrapped in a \
104435933ddSDimitry Andric generated function, and a call to the function will be attached to the breakpoint."
105435933ddSDimitry Andric         R"(
106b91a7dfcSDimitry Andric 
107b91a7dfcSDimitry Andric This auto-generated function is passed in three arguments:
108b91a7dfcSDimitry Andric 
109b91a7dfcSDimitry Andric     frame:  an lldb.SBFrame object for the frame which hit breakpoint.
110b91a7dfcSDimitry Andric 
111b91a7dfcSDimitry Andric     bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
112b91a7dfcSDimitry Andric 
113b91a7dfcSDimitry Andric     dict:   the python session dictionary hit.
114b91a7dfcSDimitry Andric 
115435933ddSDimitry Andric )"
116435933ddSDimitry Andric         "When specifying a python function with the --python-function option, you need \
117435933ddSDimitry Andric to supply the function name prepended by the module name:"
118435933ddSDimitry Andric         R"(
119b91a7dfcSDimitry Andric 
120b91a7dfcSDimitry Andric     --python-function myutils.breakpoint_callback
121b91a7dfcSDimitry Andric 
122b91a7dfcSDimitry Andric The function itself must have the following prototype:
123b91a7dfcSDimitry Andric 
124b91a7dfcSDimitry Andric def breakpoint_callback(frame, bp_loc, dict):
125b91a7dfcSDimitry Andric   # Your code goes here
126b91a7dfcSDimitry Andric 
127435933ddSDimitry Andric )"
128435933ddSDimitry Andric         "The arguments are the same as the arguments passed to generated functions as \
129b91a7dfcSDimitry Andric described above.  Note that the global variable 'lldb.frame' will NOT be updated when \
130b91a7dfcSDimitry Andric this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
131b91a7dfcSDimitry Andric can get you to the thread via frame.GetThread(), the thread can get you to the \
132b91a7dfcSDimitry Andric process via thread.GetProcess(), and the process can get you back to the target \
133435933ddSDimitry Andric via process.GetTarget()."
134435933ddSDimitry Andric         R"(
135b91a7dfcSDimitry Andric 
136435933ddSDimitry Andric )"
137435933ddSDimitry Andric         "Important Note: As Python code gets collected into functions, access to global \
138b91a7dfcSDimitry Andric variables requires explicit scoping using the 'global' keyword.  Be sure to use correct \
139435933ddSDimitry Andric Python syntax, including indentation, when entering Python breakpoint commands."
140435933ddSDimitry Andric         R"(
141b91a7dfcSDimitry Andric 
142b91a7dfcSDimitry Andric Example Python one-line breakpoint command:
143b91a7dfcSDimitry Andric 
144b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1
145b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
146b91a7dfcSDimitry Andric > print "Hit this breakpoint!"
147b91a7dfcSDimitry Andric > DONE
148b91a7dfcSDimitry Andric 
149b91a7dfcSDimitry Andric As a convenience, this also works for a short Python one-liner:
150b91a7dfcSDimitry Andric 
151b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
152b91a7dfcSDimitry Andric (lldb) run
153b91a7dfcSDimitry Andric Launching '.../a.out'  (x86_64)
154b91a7dfcSDimitry Andric (lldb) Fri Sep 10 12:17:45 2010
155b91a7dfcSDimitry Andric Process 21778 Stopped
156b91a7dfcSDimitry Andric * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
157b91a7dfcSDimitry Andric   36
158b91a7dfcSDimitry Andric   37   	int c(int val)
159b91a7dfcSDimitry Andric   38   	{
160b91a7dfcSDimitry Andric   39 ->	    return val + 3;
161b91a7dfcSDimitry Andric   40   	}
162b91a7dfcSDimitry Andric   41
163b91a7dfcSDimitry Andric   42   	int main (int argc, char const *argv[])
164b91a7dfcSDimitry Andric 
165b91a7dfcSDimitry Andric Example multiple line Python breakpoint command:
166b91a7dfcSDimitry Andric 
167b91a7dfcSDimitry Andric (lldb) breakpoint command add -s p 1
168b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
169b91a7dfcSDimitry Andric > global bp_count
170b91a7dfcSDimitry Andric > bp_count = bp_count + 1
171b91a7dfcSDimitry Andric > print "Hit this breakpoint " + repr(bp_count) + " times!"
172b91a7dfcSDimitry Andric > DONE
173b91a7dfcSDimitry Andric 
174b91a7dfcSDimitry Andric Example multiple line Python breakpoint command, using function definition:
175b91a7dfcSDimitry Andric 
176b91a7dfcSDimitry Andric (lldb) breakpoint command add -s python 1
177b91a7dfcSDimitry Andric Enter your Python command(s). Type 'DONE' to end.
178b91a7dfcSDimitry Andric > def breakpoint_output (bp_no):
179b91a7dfcSDimitry Andric >     out_string = "Hit breakpoint number " + repr (bp_no)
180b91a7dfcSDimitry Andric >     print out_string
181b91a7dfcSDimitry Andric >     return True
182b91a7dfcSDimitry Andric > breakpoint_output (1)
183b91a7dfcSDimitry Andric > DONE
184b91a7dfcSDimitry Andric 
185435933ddSDimitry Andric )"
186435933ddSDimitry Andric         "In this case, since there is a reference to a global variable, \
187b91a7dfcSDimitry Andric 'bp_count', you will also need to make sure 'bp_count' exists and is \
188435933ddSDimitry Andric initialized:"
189435933ddSDimitry Andric         R"(
190b91a7dfcSDimitry Andric 
191b91a7dfcSDimitry Andric (lldb) script
192b91a7dfcSDimitry Andric >>> bp_count = 0
193b91a7dfcSDimitry Andric >>> quit()
194b91a7dfcSDimitry Andric 
195435933ddSDimitry Andric )"
196435933ddSDimitry Andric         "Your Python code, however organized, can optionally return a value.  \
197b91a7dfcSDimitry Andric If the returned value is False, that tells LLDB not to stop at the breakpoint \
198b91a7dfcSDimitry Andric to which the code is associated. Returning anything other than False, or even \
199b91a7dfcSDimitry Andric returning None, or even omitting a return statement entirely, will cause \
200435933ddSDimitry Andric LLDB to stop."
201435933ddSDimitry Andric         R"(
202b91a7dfcSDimitry Andric 
203435933ddSDimitry Andric )"
204435933ddSDimitry Andric         "Final Note: A warning that no breakpoint command was generated when there \
205435933ddSDimitry Andric are no syntax errors may indicate that a function was declared but never called.");
206ac7ddfbfSEd Maste 
207ac7ddfbfSEd Maste     CommandArgumentEntry arg;
208ac7ddfbfSEd Maste     CommandArgumentData bp_id_arg;
209ac7ddfbfSEd Maste 
210ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
211ac7ddfbfSEd Maste     bp_id_arg.arg_type = eArgTypeBreakpointID;
2120127ef0fSEd Maste     bp_id_arg.arg_repetition = eArgRepeatOptional;
213ac7ddfbfSEd Maste 
214435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
215435933ddSDimitry Andric     // argument entry.
216ac7ddfbfSEd Maste     arg.push_back(bp_id_arg);
217ac7ddfbfSEd Maste 
218ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
219ac7ddfbfSEd Maste     m_arguments.push_back(arg);
220ac7ddfbfSEd Maste   }
221ac7ddfbfSEd Maste 
2224bb0738eSEd Maste   ~CommandObjectBreakpointCommandAdd() override = default;
223ac7ddfbfSEd Maste 
GetOptions()224435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
225ac7ddfbfSEd Maste 
IOHandlerActivated(IOHandler & io_handler)226435933ddSDimitry Andric   void IOHandlerActivated(IOHandler &io_handler) override {
22712b93ac6SEd Maste     StreamFileSP output_sp(io_handler.GetOutputStreamFile());
228435933ddSDimitry Andric     if (output_sp) {
22912b93ac6SEd Maste       output_sp->PutCString(g_reader_instructions);
23012b93ac6SEd Maste       output_sp->Flush();
23112b93ac6SEd Maste     }
23212b93ac6SEd Maste   }
23312b93ac6SEd Maste 
IOHandlerInputComplete(IOHandler & io_handler,std::string & line)234435933ddSDimitry Andric   void IOHandlerInputComplete(IOHandler &io_handler,
235435933ddSDimitry Andric                               std::string &line) override {
23612b93ac6SEd Maste     io_handler.SetIsDone(true);
23712b93ac6SEd Maste 
238435933ddSDimitry Andric     std::vector<BreakpointOptions *> *bp_options_vec =
239435933ddSDimitry Andric         (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
240435933ddSDimitry Andric     for (BreakpointOptions *bp_options : *bp_options_vec) {
2410127ef0fSEd Maste       if (!bp_options)
2420127ef0fSEd Maste         continue;
2430127ef0fSEd Maste 
244435933ddSDimitry Andric       auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
245435933ddSDimitry Andric       cmd_data->user_source.SplitIntoLines(line.c_str(), line.size());
246435933ddSDimitry Andric       bp_options->SetCommandDataCallback(cmd_data);
24712b93ac6SEd Maste     }
24812b93ac6SEd Maste   }
24912b93ac6SEd Maste 
CollectDataForBreakpointCommandCallback(std::vector<BreakpointOptions * > & bp_options_vec,CommandReturnObject & result)250435933ddSDimitry Andric   void CollectDataForBreakpointCommandCallback(
251435933ddSDimitry Andric       std::vector<BreakpointOptions *> &bp_options_vec,
252435933ddSDimitry Andric       CommandReturnObject &result) {
253435933ddSDimitry Andric     m_interpreter.GetLLDBCommandsFromIOHandler(
254435933ddSDimitry Andric         "> ",             // Prompt
25512b93ac6SEd Maste         *this,            // IOHandlerDelegate
25612b93ac6SEd Maste         true,             // Run IOHandler in async mode
257435933ddSDimitry Andric         &bp_options_vec); // Baton for the "io_handler" that will be passed back
258435933ddSDimitry Andric                           // into our IOHandlerDelegate functions
259ac7ddfbfSEd Maste   }
260ac7ddfbfSEd Maste 
261ac7ddfbfSEd Maste   /// Set a one-liner as the callback for the breakpoint.
262ac7ddfbfSEd Maste   void
SetBreakpointCommandCallback(std::vector<BreakpointOptions * > & bp_options_vec,const char * oneliner)2630127ef0fSEd Maste   SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec,
264435933ddSDimitry Andric                                const char *oneliner) {
265435933ddSDimitry Andric     for (auto bp_options : bp_options_vec) {
266435933ddSDimitry Andric       auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>();
267ac7ddfbfSEd Maste 
268435933ddSDimitry Andric       cmd_data->user_source.AppendString(oneliner);
269435933ddSDimitry Andric       cmd_data->stop_on_error = m_options.m_stop_on_error;
270ac7ddfbfSEd Maste 
271435933ddSDimitry Andric       bp_options->SetCommandDataCallback(cmd_data);
2720127ef0fSEd Maste     }
273ac7ddfbfSEd Maste   }
274ac7ddfbfSEd Maste 
275435933ddSDimitry Andric   class CommandOptions : public Options {
276ac7ddfbfSEd Maste   public:
CommandOptions()277435933ddSDimitry Andric     CommandOptions()
278435933ddSDimitry Andric         : Options(), m_use_commands(false), m_use_script_language(false),
279435933ddSDimitry Andric           m_script_language(eScriptLanguageNone), m_use_one_liner(false),
280435933ddSDimitry Andric           m_one_liner(), m_function_name() {}
281ac7ddfbfSEd Maste 
2824bb0738eSEd Maste     ~CommandOptions() override = default;
283ac7ddfbfSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2845517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
285435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
2865517e702SDimitry Andric       Status error;
287ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
288ac7ddfbfSEd Maste 
289435933ddSDimitry Andric       switch (short_option) {
290ac7ddfbfSEd Maste       case 'o':
291ac7ddfbfSEd Maste         m_use_one_liner = true;
292ac7ddfbfSEd Maste         m_one_liner = option_arg;
293ac7ddfbfSEd Maste         break;
294ac7ddfbfSEd Maste 
295ac7ddfbfSEd Maste       case 's':
2964ba319b5SDimitry Andric         m_script_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
297435933ddSDimitry Andric             option_arg, g_breakpoint_add_options[option_idx].enum_values,
298435933ddSDimitry Andric             eScriptLanguageNone, error);
299ac7ddfbfSEd Maste 
300435933ddSDimitry Andric         if (m_script_language == eScriptLanguagePython ||
301435933ddSDimitry Andric             m_script_language == eScriptLanguageDefault) {
302ac7ddfbfSEd Maste           m_use_script_language = true;
303435933ddSDimitry Andric         } else {
304ac7ddfbfSEd Maste           m_use_script_language = false;
305ac7ddfbfSEd Maste         }
306ac7ddfbfSEd Maste         break;
307ac7ddfbfSEd Maste 
308435933ddSDimitry Andric       case 'e': {
309ac7ddfbfSEd Maste         bool success = false;
3104ba319b5SDimitry Andric         m_stop_on_error =
3114ba319b5SDimitry Andric             OptionArgParser::ToBoolean(option_arg, false, &success);
312ac7ddfbfSEd Maste         if (!success)
313435933ddSDimitry Andric           error.SetErrorStringWithFormat(
314435933ddSDimitry Andric               "invalid value for stop-on-error: \"%s\"",
315435933ddSDimitry Andric               option_arg.str().c_str());
316435933ddSDimitry Andric       } break;
317ac7ddfbfSEd Maste 
318ac7ddfbfSEd Maste       case 'F':
319ac7ddfbfSEd Maste         m_use_one_liner = false;
320ac7ddfbfSEd Maste         m_use_script_language = true;
321ac7ddfbfSEd Maste         m_function_name.assign(option_arg);
322ac7ddfbfSEd Maste         break;
323ac7ddfbfSEd Maste 
3247aa51b79SEd Maste       case 'D':
3257aa51b79SEd Maste         m_use_dummy = true;
3267aa51b79SEd Maste         break;
3277aa51b79SEd Maste 
328ac7ddfbfSEd Maste       default:
329ac7ddfbfSEd Maste         break;
330ac7ddfbfSEd Maste       }
331ac7ddfbfSEd Maste       return error;
332ac7ddfbfSEd Maste     }
3334bb0738eSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)334435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
335ac7ddfbfSEd Maste       m_use_commands = true;
336ac7ddfbfSEd Maste       m_use_script_language = false;
337ac7ddfbfSEd Maste       m_script_language = eScriptLanguageNone;
338ac7ddfbfSEd Maste 
339ac7ddfbfSEd Maste       m_use_one_liner = false;
340ac7ddfbfSEd Maste       m_stop_on_error = true;
341ac7ddfbfSEd Maste       m_one_liner.clear();
342ac7ddfbfSEd Maste       m_function_name.clear();
3437aa51b79SEd Maste       m_use_dummy = false;
344ac7ddfbfSEd Maste     }
345ac7ddfbfSEd Maste 
GetDefinitions()346435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
347435933ddSDimitry Andric       return llvm::makeArrayRef(g_breakpoint_add_options);
348ac7ddfbfSEd Maste     }
349ac7ddfbfSEd Maste 
350ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
351ac7ddfbfSEd Maste 
352ac7ddfbfSEd Maste     bool m_use_commands;
353ac7ddfbfSEd Maste     bool m_use_script_language;
354ac7ddfbfSEd Maste     lldb::ScriptLanguage m_script_language;
355ac7ddfbfSEd Maste 
356ac7ddfbfSEd Maste     // Instance variables to hold the values for one_liner options.
357ac7ddfbfSEd Maste     bool m_use_one_liner;
358ac7ddfbfSEd Maste     std::string m_one_liner;
359ac7ddfbfSEd Maste     bool m_stop_on_error;
360ac7ddfbfSEd Maste     std::string m_function_name;
3617aa51b79SEd Maste     bool m_use_dummy;
362ac7ddfbfSEd Maste   };
363ac7ddfbfSEd Maste 
364ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)365435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
3667aa51b79SEd Maste     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
367ac7ddfbfSEd Maste 
368435933ddSDimitry Andric     if (target == nullptr) {
369435933ddSDimitry Andric       result.AppendError("There is not a current executable; there are no "
370435933ddSDimitry Andric                          "breakpoints to which to add commands");
371ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
372ac7ddfbfSEd Maste       return false;
373ac7ddfbfSEd Maste     }
374ac7ddfbfSEd Maste 
375ac7ddfbfSEd Maste     const BreakpointList &breakpoints = target->GetBreakpointList();
376ac7ddfbfSEd Maste     size_t num_breakpoints = breakpoints.GetSize();
377ac7ddfbfSEd Maste 
378435933ddSDimitry Andric     if (num_breakpoints == 0) {
379ac7ddfbfSEd Maste       result.AppendError("No breakpoints exist to have commands added");
380ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
381ac7ddfbfSEd Maste       return false;
382ac7ddfbfSEd Maste     }
383ac7ddfbfSEd Maste 
384435933ddSDimitry Andric     if (!m_options.m_use_script_language &&
385435933ddSDimitry Andric         !m_options.m_function_name.empty()) {
386435933ddSDimitry Andric       result.AppendError("need to enable scripting to have a function run as a "
387435933ddSDimitry Andric                          "breakpoint command");
388ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
389ac7ddfbfSEd Maste       return false;
390ac7ddfbfSEd Maste     }
391ac7ddfbfSEd Maste 
392ac7ddfbfSEd Maste     BreakpointIDList valid_bp_ids;
393435933ddSDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
394acac075bSDimitry Andric         command, target, result, &valid_bp_ids,
395acac075bSDimitry Andric         BreakpointName::Permissions::PermissionKinds::listPerm);
396ac7ddfbfSEd Maste 
3970127ef0fSEd Maste     m_bp_options_vec.clear();
3980127ef0fSEd Maste 
399435933ddSDimitry Andric     if (result.Succeeded()) {
400ac7ddfbfSEd Maste       const size_t count = valid_bp_ids.GetSize();
401ac7ddfbfSEd Maste 
402435933ddSDimitry Andric       for (size_t i = 0; i < count; ++i) {
403ac7ddfbfSEd Maste         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
404435933ddSDimitry Andric         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
405435933ddSDimitry Andric           Breakpoint *bp =
406435933ddSDimitry Andric               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
4074bb0738eSEd Maste           BreakpointOptions *bp_options = nullptr;
408435933ddSDimitry Andric           if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) {
409ac7ddfbfSEd Maste             // This breakpoint does not have an associated location.
410ac7ddfbfSEd Maste             bp_options = bp->GetOptions();
411435933ddSDimitry Andric           } else {
412435933ddSDimitry Andric             BreakpointLocationSP bp_loc_sp(
413435933ddSDimitry Andric                 bp->FindLocationByID(cur_bp_id.GetLocationID()));
4144ba319b5SDimitry Andric             // This breakpoint does have an associated location. Get its
4154ba319b5SDimitry Andric             // breakpoint options.
416ac7ddfbfSEd Maste             if (bp_loc_sp)
417ac7ddfbfSEd Maste               bp_options = bp_loc_sp->GetLocationOptions();
418ac7ddfbfSEd Maste           }
4190127ef0fSEd Maste           if (bp_options)
4200127ef0fSEd Maste             m_bp_options_vec.push_back(bp_options);
4210127ef0fSEd Maste         }
4220127ef0fSEd Maste       }
423ac7ddfbfSEd Maste 
4244ba319b5SDimitry Andric       // If we are using script language, get the script interpreter in order
4254ba319b5SDimitry Andric       // to set or collect command callback.  Otherwise, call the methods
4264ba319b5SDimitry Andric       // associated with this object.
427435933ddSDimitry Andric       if (m_options.m_use_script_language) {
4280127ef0fSEd Maste         ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
429ac7ddfbfSEd Maste         // Special handling for one-liner specified inline.
430435933ddSDimitry Andric         if (m_options.m_use_one_liner) {
431435933ddSDimitry Andric           script_interp->SetBreakpointCommandCallback(
432435933ddSDimitry Andric               m_bp_options_vec, m_options.m_one_liner.c_str());
433435933ddSDimitry Andric         } else if (!m_options.m_function_name.empty()) {
434435933ddSDimitry Andric           script_interp->SetBreakpointCommandCallbackFunction(
435435933ddSDimitry Andric               m_bp_options_vec, m_options.m_function_name.c_str());
436435933ddSDimitry Andric         } else {
437435933ddSDimitry Andric           script_interp->CollectDataForBreakpointCommandCallback(
438435933ddSDimitry Andric               m_bp_options_vec, result);
439ac7ddfbfSEd Maste         }
440435933ddSDimitry Andric       } else {
441ac7ddfbfSEd Maste         // Special handling for one-liner specified inline.
442ac7ddfbfSEd Maste         if (m_options.m_use_one_liner)
4430127ef0fSEd Maste           SetBreakpointCommandCallback(m_bp_options_vec,
444ac7ddfbfSEd Maste                                        m_options.m_one_liner.c_str());
445ac7ddfbfSEd Maste         else
446435933ddSDimitry Andric           CollectDataForBreakpointCommandCallback(m_bp_options_vec, result);
447ac7ddfbfSEd Maste       }
448ac7ddfbfSEd Maste     }
449ac7ddfbfSEd Maste 
450ac7ddfbfSEd Maste     return result.Succeeded();
451ac7ddfbfSEd Maste   }
452ac7ddfbfSEd Maste 
453ac7ddfbfSEd Maste private:
454ac7ddfbfSEd Maste   CommandOptions m_options;
455435933ddSDimitry Andric   std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the
456435933ddSDimitry Andric                                                      // breakpoint options that
457435933ddSDimitry Andric                                                      // we are currently
4584ba319b5SDimitry Andric   // collecting commands for.  In the CollectData... calls we need to hand this
4594ba319b5SDimitry Andric   // off to the IOHandler, which may run asynchronously. So we have to have
4604ba319b5SDimitry Andric   // some way to keep it alive, and not leak it. Making it an ivar of the
4614ba319b5SDimitry Andric   // command object, which never goes away achieves this.  Note that if we were
4624ba319b5SDimitry Andric   // able to run the same command concurrently in one interpreter we'd have to
4634ba319b5SDimitry Andric   // make this "per invocation".  But there are many more reasons why it is not
4644ba319b5SDimitry Andric   // in general safe to do that in lldb at present, so it isn't worthwhile to
4654ba319b5SDimitry Andric   // come up with a more complex mechanism to address this particular weakness
4664ba319b5SDimitry Andric   // right now.
467ac7ddfbfSEd Maste   static const char *g_reader_instructions;
468ac7ddfbfSEd Maste };
469ac7ddfbfSEd Maste 
470435933ddSDimitry Andric const char *CommandObjectBreakpointCommandAdd::g_reader_instructions =
471435933ddSDimitry Andric     "Enter your debugger command(s).  Type 'DONE' to end.\n";
472ac7ddfbfSEd Maste 
473ac7ddfbfSEd Maste //-------------------------------------------------------------------------
474ac7ddfbfSEd Maste // CommandObjectBreakpointCommandDelete
475ac7ddfbfSEd Maste //-------------------------------------------------------------------------
476ac7ddfbfSEd Maste 
477*b5893f02SDimitry Andric static constexpr OptionDefinition g_breakpoint_delete_options[] = {
478435933ddSDimitry Andric     // clang-format off
479*b5893f02SDimitry Andric   { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." },
480435933ddSDimitry Andric     // clang-format on
481435933ddSDimitry Andric };
482435933ddSDimitry Andric 
483435933ddSDimitry Andric class CommandObjectBreakpointCommandDelete : public CommandObjectParsed {
484ac7ddfbfSEd Maste public:
CommandObjectBreakpointCommandDelete(CommandInterpreter & interpreter)485435933ddSDimitry Andric   CommandObjectBreakpointCommandDelete(CommandInterpreter &interpreter)
486435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "delete",
487ac7ddfbfSEd Maste                             "Delete the set of commands from a breakpoint.",
4884bb0738eSEd Maste                             nullptr),
489435933ddSDimitry Andric         m_options() {
490ac7ddfbfSEd Maste     CommandArgumentEntry arg;
491ac7ddfbfSEd Maste     CommandArgumentData bp_id_arg;
492ac7ddfbfSEd Maste 
493ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
494ac7ddfbfSEd Maste     bp_id_arg.arg_type = eArgTypeBreakpointID;
495ac7ddfbfSEd Maste     bp_id_arg.arg_repetition = eArgRepeatPlain;
496ac7ddfbfSEd Maste 
497435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
498435933ddSDimitry Andric     // argument entry.
499ac7ddfbfSEd Maste     arg.push_back(bp_id_arg);
500ac7ddfbfSEd Maste 
501ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
502ac7ddfbfSEd Maste     m_arguments.push_back(arg);
503ac7ddfbfSEd Maste   }
504ac7ddfbfSEd Maste 
5054bb0738eSEd Maste   ~CommandObjectBreakpointCommandDelete() override = default;
506ac7ddfbfSEd Maste 
GetOptions()507435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
5087aa51b79SEd Maste 
509435933ddSDimitry Andric   class CommandOptions : public Options {
5107aa51b79SEd Maste   public:
CommandOptions()511435933ddSDimitry Andric     CommandOptions() : Options(), m_use_dummy(false) {}
5127aa51b79SEd Maste 
5134bb0738eSEd Maste     ~CommandOptions() override = default;
5147aa51b79SEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)5155517e702SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
516435933ddSDimitry Andric                           ExecutionContext *execution_context) override {
5175517e702SDimitry Andric       Status error;
5187aa51b79SEd Maste       const int short_option = m_getopt_table[option_idx].val;
5197aa51b79SEd Maste 
520435933ddSDimitry Andric       switch (short_option) {
5217aa51b79SEd Maste       case 'D':
5227aa51b79SEd Maste         m_use_dummy = true;
5237aa51b79SEd Maste         break;
5247aa51b79SEd Maste 
5257aa51b79SEd Maste       default:
526435933ddSDimitry Andric         error.SetErrorStringWithFormat("unrecognized option '%c'",
527435933ddSDimitry Andric                                        short_option);
5287aa51b79SEd Maste         break;
5297aa51b79SEd Maste       }
5307aa51b79SEd Maste 
5317aa51b79SEd Maste       return error;
5327aa51b79SEd Maste     }
5337aa51b79SEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)534435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
5357aa51b79SEd Maste       m_use_dummy = false;
5367aa51b79SEd Maste     }
5377aa51b79SEd Maste 
GetDefinitions()538435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
539435933ddSDimitry Andric       return llvm::makeArrayRef(g_breakpoint_delete_options);
5407aa51b79SEd Maste     }
5417aa51b79SEd Maste 
5427aa51b79SEd Maste     // Instance variables to hold the values for command options.
5437aa51b79SEd Maste     bool m_use_dummy;
5447aa51b79SEd Maste   };
5457aa51b79SEd Maste 
546ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)547435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
5487aa51b79SEd Maste     Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
549ac7ddfbfSEd Maste 
550435933ddSDimitry Andric     if (target == nullptr) {
551435933ddSDimitry Andric       result.AppendError("There is not a current executable; there are no "
552435933ddSDimitry Andric                          "breakpoints from which to delete commands");
553ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
554ac7ddfbfSEd Maste       return false;
555ac7ddfbfSEd Maste     }
556ac7ddfbfSEd Maste 
557ac7ddfbfSEd Maste     const BreakpointList &breakpoints = target->GetBreakpointList();
558ac7ddfbfSEd Maste     size_t num_breakpoints = breakpoints.GetSize();
559ac7ddfbfSEd Maste 
560435933ddSDimitry Andric     if (num_breakpoints == 0) {
561ac7ddfbfSEd Maste       result.AppendError("No breakpoints exist to have commands deleted");
562ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
563ac7ddfbfSEd Maste       return false;
564ac7ddfbfSEd Maste     }
565ac7ddfbfSEd Maste 
566435933ddSDimitry Andric     if (command.empty()) {
567435933ddSDimitry Andric       result.AppendError(
568435933ddSDimitry Andric           "No breakpoint specified from which to delete the commands");
569ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
570ac7ddfbfSEd Maste       return false;
571ac7ddfbfSEd Maste     }
572ac7ddfbfSEd Maste 
573ac7ddfbfSEd Maste     BreakpointIDList valid_bp_ids;
574435933ddSDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
575acac075bSDimitry Andric         command, target, result, &valid_bp_ids,
576acac075bSDimitry Andric         BreakpointName::Permissions::PermissionKinds::listPerm);
577ac7ddfbfSEd Maste 
578435933ddSDimitry Andric     if (result.Succeeded()) {
579ac7ddfbfSEd Maste       const size_t count = valid_bp_ids.GetSize();
580435933ddSDimitry Andric       for (size_t i = 0; i < count; ++i) {
581ac7ddfbfSEd Maste         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
582435933ddSDimitry Andric         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
583435933ddSDimitry Andric           Breakpoint *bp =
584435933ddSDimitry Andric               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
585435933ddSDimitry Andric           if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
586435933ddSDimitry Andric             BreakpointLocationSP bp_loc_sp(
587435933ddSDimitry Andric                 bp->FindLocationByID(cur_bp_id.GetLocationID()));
588ac7ddfbfSEd Maste             if (bp_loc_sp)
589ac7ddfbfSEd Maste               bp_loc_sp->ClearCallback();
590435933ddSDimitry Andric             else {
591ac7ddfbfSEd Maste               result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
592ac7ddfbfSEd Maste                                            cur_bp_id.GetBreakpointID(),
593ac7ddfbfSEd Maste                                            cur_bp_id.GetLocationID());
594ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
595ac7ddfbfSEd Maste               return false;
596ac7ddfbfSEd Maste             }
597435933ddSDimitry Andric           } else {
598ac7ddfbfSEd Maste             bp->ClearCallback();
599ac7ddfbfSEd Maste           }
600ac7ddfbfSEd Maste         }
601ac7ddfbfSEd Maste       }
602ac7ddfbfSEd Maste     }
603ac7ddfbfSEd Maste     return result.Succeeded();
604ac7ddfbfSEd Maste   }
6054bb0738eSEd Maste 
6067aa51b79SEd Maste private:
6077aa51b79SEd Maste   CommandOptions m_options;
608ac7ddfbfSEd Maste };
609ac7ddfbfSEd Maste 
610ac7ddfbfSEd Maste //-------------------------------------------------------------------------
611ac7ddfbfSEd Maste // CommandObjectBreakpointCommandList
612ac7ddfbfSEd Maste //-------------------------------------------------------------------------
613ac7ddfbfSEd Maste 
614435933ddSDimitry Andric class CommandObjectBreakpointCommandList : public CommandObjectParsed {
615ac7ddfbfSEd Maste public:
CommandObjectBreakpointCommandList(CommandInterpreter & interpreter)616435933ddSDimitry Andric   CommandObjectBreakpointCommandList(CommandInterpreter &interpreter)
617435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "list", "List the script or set of "
618435933ddSDimitry Andric                                                  "commands to be executed when "
619435933ddSDimitry Andric                                                  "the breakpoint is hit.",
620435933ddSDimitry Andric                             nullptr) {
621ac7ddfbfSEd Maste     CommandArgumentEntry arg;
622ac7ddfbfSEd Maste     CommandArgumentData bp_id_arg;
623ac7ddfbfSEd Maste 
624ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
625ac7ddfbfSEd Maste     bp_id_arg.arg_type = eArgTypeBreakpointID;
626ac7ddfbfSEd Maste     bp_id_arg.arg_repetition = eArgRepeatPlain;
627ac7ddfbfSEd Maste 
628435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
629435933ddSDimitry Andric     // argument entry.
630ac7ddfbfSEd Maste     arg.push_back(bp_id_arg);
631ac7ddfbfSEd Maste 
632ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
633ac7ddfbfSEd Maste     m_arguments.push_back(arg);
634ac7ddfbfSEd Maste   }
635ac7ddfbfSEd Maste 
6364bb0738eSEd Maste   ~CommandObjectBreakpointCommandList() override = default;
637ac7ddfbfSEd Maste 
638ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)639435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
640ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
641ac7ddfbfSEd Maste 
642435933ddSDimitry Andric     if (target == nullptr) {
643435933ddSDimitry Andric       result.AppendError("There is not a current executable; there are no "
644435933ddSDimitry Andric                          "breakpoints for which to list commands");
645ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
646ac7ddfbfSEd Maste       return false;
647ac7ddfbfSEd Maste     }
648ac7ddfbfSEd Maste 
649ac7ddfbfSEd Maste     const BreakpointList &breakpoints = target->GetBreakpointList();
650ac7ddfbfSEd Maste     size_t num_breakpoints = breakpoints.GetSize();
651ac7ddfbfSEd Maste 
652435933ddSDimitry Andric     if (num_breakpoints == 0) {
653ac7ddfbfSEd Maste       result.AppendError("No breakpoints exist for which to list commands");
654ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
655ac7ddfbfSEd Maste       return false;
656ac7ddfbfSEd Maste     }
657ac7ddfbfSEd Maste 
658435933ddSDimitry Andric     if (command.empty()) {
659435933ddSDimitry Andric       result.AppendError(
660435933ddSDimitry Andric           "No breakpoint specified for which to list the commands");
661ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
662ac7ddfbfSEd Maste       return false;
663ac7ddfbfSEd Maste     }
664ac7ddfbfSEd Maste 
665ac7ddfbfSEd Maste     BreakpointIDList valid_bp_ids;
666435933ddSDimitry Andric     CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
667acac075bSDimitry Andric         command, target, result, &valid_bp_ids,
668acac075bSDimitry Andric         BreakpointName::Permissions::PermissionKinds::listPerm);
669ac7ddfbfSEd Maste 
670435933ddSDimitry Andric     if (result.Succeeded()) {
671ac7ddfbfSEd Maste       const size_t count = valid_bp_ids.GetSize();
672435933ddSDimitry Andric       for (size_t i = 0; i < count; ++i) {
673ac7ddfbfSEd Maste         BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
674435933ddSDimitry Andric         if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
675435933ddSDimitry Andric           Breakpoint *bp =
676435933ddSDimitry Andric               target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
677ac7ddfbfSEd Maste 
678435933ddSDimitry Andric           if (bp) {
679acac075bSDimitry Andric             BreakpointLocationSP bp_loc_sp;
680435933ddSDimitry Andric             if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
681acac075bSDimitry Andric                   bp_loc_sp = bp->FindLocationByID(cur_bp_id.GetLocationID());
682acac075bSDimitry Andric               if (!bp_loc_sp)
683acac075bSDimitry Andric               {
684ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
685ac7ddfbfSEd Maste                                              cur_bp_id.GetBreakpointID(),
686ac7ddfbfSEd Maste                                              cur_bp_id.GetLocationID());
687ac7ddfbfSEd Maste                 result.SetStatus(eReturnStatusFailed);
688ac7ddfbfSEd Maste                 return false;
689ac7ddfbfSEd Maste               }
690ac7ddfbfSEd Maste             }
691ac7ddfbfSEd Maste 
692ac7ddfbfSEd Maste             StreamString id_str;
693ac7ddfbfSEd Maste             BreakpointID::GetCanonicalReference(&id_str,
694ac7ddfbfSEd Maste                                                 cur_bp_id.GetBreakpointID(),
695ac7ddfbfSEd Maste                                                 cur_bp_id.GetLocationID());
696acac075bSDimitry Andric             const Baton *baton = nullptr;
697acac075bSDimitry Andric             if (bp_loc_sp)
698acac075bSDimitry Andric               baton = bp_loc_sp
699acac075bSDimitry Andric                ->GetOptionsSpecifyingKind(BreakpointOptions::eCallback)
700acac075bSDimitry Andric                ->GetBaton();
701acac075bSDimitry Andric             else
702acac075bSDimitry Andric               baton = bp->GetOptions()->GetBaton();
703acac075bSDimitry Andric 
704435933ddSDimitry Andric             if (baton) {
705435933ddSDimitry Andric               result.GetOutputStream().Printf("Breakpoint %s:\n",
706435933ddSDimitry Andric                                               id_str.GetData());
707ac7ddfbfSEd Maste               result.GetOutputStream().IndentMore();
708435933ddSDimitry Andric               baton->GetDescription(&result.GetOutputStream(),
709435933ddSDimitry Andric                                     eDescriptionLevelFull);
710ac7ddfbfSEd Maste               result.GetOutputStream().IndentLess();
711435933ddSDimitry Andric             } else {
712435933ddSDimitry Andric               result.AppendMessageWithFormat(
713435933ddSDimitry Andric                   "Breakpoint %s does not have an associated command.\n",
714ac7ddfbfSEd Maste                   id_str.GetData());
715ac7ddfbfSEd Maste             }
716ac7ddfbfSEd Maste           }
717ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
718435933ddSDimitry Andric         } else {
719435933ddSDimitry Andric           result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n",
720435933ddSDimitry Andric                                        cur_bp_id.GetBreakpointID());
721ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
722ac7ddfbfSEd Maste         }
723ac7ddfbfSEd Maste       }
724ac7ddfbfSEd Maste     }
725ac7ddfbfSEd Maste 
726ac7ddfbfSEd Maste     return result.Succeeded();
727ac7ddfbfSEd Maste   }
728ac7ddfbfSEd Maste };
729ac7ddfbfSEd Maste 
730ac7ddfbfSEd Maste //-------------------------------------------------------------------------
731ac7ddfbfSEd Maste // CommandObjectBreakpointCommand
732ac7ddfbfSEd Maste //-------------------------------------------------------------------------
733ac7ddfbfSEd Maste 
CommandObjectBreakpointCommand(CommandInterpreter & interpreter)734435933ddSDimitry Andric CommandObjectBreakpointCommand::CommandObjectBreakpointCommand(
735435933ddSDimitry Andric     CommandInterpreter &interpreter)
7364bb0738eSEd Maste     : CommandObjectMultiword(
737435933ddSDimitry Andric           interpreter, "command", "Commands for adding, removing and listing "
738435933ddSDimitry Andric                                   "LLDB commands executed when a breakpoint is "
739435933ddSDimitry Andric                                   "hit.",
740435933ddSDimitry Andric           "command <sub-command> [<sub-command-options>] <breakpoint-id>") {
741435933ddSDimitry Andric   CommandObjectSP add_command_object(
742435933ddSDimitry Andric       new CommandObjectBreakpointCommandAdd(interpreter));
743435933ddSDimitry Andric   CommandObjectSP delete_command_object(
744435933ddSDimitry Andric       new CommandObjectBreakpointCommandDelete(interpreter));
745435933ddSDimitry Andric   CommandObjectSP list_command_object(
746435933ddSDimitry Andric       new CommandObjectBreakpointCommandList(interpreter));
747ac7ddfbfSEd Maste 
748ac7ddfbfSEd Maste   add_command_object->SetCommandName("breakpoint command add");
749ac7ddfbfSEd Maste   delete_command_object->SetCommandName("breakpoint command delete");
750ac7ddfbfSEd Maste   list_command_object->SetCommandName("breakpoint command list");
751ac7ddfbfSEd Maste 
752ac7ddfbfSEd Maste   LoadSubCommand("add", add_command_object);
753ac7ddfbfSEd Maste   LoadSubCommand("delete", delete_command_object);
754ac7ddfbfSEd Maste   LoadSubCommand("list", list_command_object);
755ac7ddfbfSEd Maste }
756ac7ddfbfSEd Maste 
7574bb0738eSEd Maste CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand() = default;
758