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