[PowerPC] Collect some CallLowering arguments into a struct. [NFC]
[llvm-project.git] / lldb / source / Commands / CommandObjectBreakpointCommand.cpp
blobbbd2ca570126668024343090fa65668597ae10d3
1 //===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectBreakpointCommand.h"
10 #include "CommandObjectBreakpoint.h"
11 #include "lldb/Breakpoint/Breakpoint.h"
12 #include "lldb/Breakpoint/BreakpointIDList.h"
13 #include "lldb/Breakpoint/BreakpointLocation.h"
14 #include "lldb/Core/IOHandler.h"
15 #include "lldb/Host/OptionParser.h"
16 #include "lldb/Interpreter/CommandInterpreter.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionArgParser.h"
19 #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
20 #include "lldb/Target/Target.h"
22 using namespace lldb;
23 using namespace lldb_private;
25 // FIXME: "script-type" needs to have its contents determined dynamically, so
26 // somebody can add a new scripting language to lldb and have it pickable here
27 // without having to change this enumeration by hand and rebuild lldb proper.
28 static constexpr OptionEnumValueElement g_script_option_enumeration[] = {
30 eScriptLanguageNone,
31 "command",
32 "Commands are in the lldb command interpreter language",
35 eScriptLanguagePython,
36 "python",
37 "Commands are in the Python language.",
40 eScriptLanguageLua,
41 "lua",
42 "Commands are in the Lua language.",
45 eScriptLanguageDefault,
46 "default-script",
47 "Commands are in the default scripting language.",
51 static constexpr OptionEnumValues ScriptOptionEnum() {
52 return OptionEnumValues(g_script_option_enumeration);
55 #define LLDB_OPTIONS_breakpoint_command_add
56 #include "CommandOptions.inc"
58 class CommandObjectBreakpointCommandAdd : public CommandObjectParsed,
59 public IOHandlerDelegateMultiline {
60 public:
61 CommandObjectBreakpointCommandAdd(CommandInterpreter &interpreter)
62 : CommandObjectParsed(interpreter, "add",
63 "Add LLDB commands to a breakpoint, to be executed "
64 "whenever the breakpoint is hit."
65 " If no breakpoint is specified, adds the "
66 "commands to the last created breakpoint.",
67 nullptr),
68 IOHandlerDelegateMultiline("DONE",
69 IOHandlerDelegate::Completion::LLDBCommand),
70 m_options(), m_func_options("breakpoint command", false, 'F') {
71 SetHelpLong(
72 R"(
73 General information about entering breakpoint commands
74 ------------------------------------------------------
77 "This command will prompt for commands to be executed when the specified \
78 breakpoint is hit. Each command is typed on its own line following the '> ' \
79 prompt until 'DONE' is entered."
80 R"(
83 "Syntactic errors may not be detected when initially entered, and many \
84 malformed commands can silently fail when executed. If your breakpoint commands \
85 do not appear to be executing, double-check the command syntax."
86 R"(
89 "Note: You may enter any debugger command exactly as you would at the debugger \
90 prompt. There is no limit to the number of commands supplied, but do NOT enter \
91 more than one command per line."
92 R"(
94 Special information about PYTHON breakpoint commands
95 ----------------------------------------------------
98 "You may enter either one or more lines of Python, including function \
99 definitions or calls to functions that will have been imported by the time \
100 the code executes. Single line breakpoint commands will be interpreted 'as is' \
101 when the breakpoint is hit. Multiple lines of Python will be wrapped in a \
102 generated function, and a call to the function will be attached to the breakpoint."
105 This auto-generated function is passed in three arguments:
107 frame: an lldb.SBFrame object for the frame which hit breakpoint.
109 bp_loc: an lldb.SBBreakpointLocation object that represents the breakpoint location that was hit.
111 dict: the python session dictionary hit.
114 "When specifying a python function with the --python-function option, you need \
115 to supply the function name prepended by the module name:"
118 --python-function myutils.breakpoint_callback
120 The function itself must have the following prototype:
122 def breakpoint_callback(frame, bp_loc, dict):
123 # Your code goes here
126 "The arguments are the same as the arguments passed to generated functions as \
127 described above. Note that the global variable 'lldb.frame' will NOT be updated when \
128 this function is called, so be sure to use the 'frame' argument. The 'frame' argument \
129 can get you to the thread via frame.GetThread(), the thread can get you to the \
130 process via thread.GetProcess(), and the process can get you back to the target \
131 via process.GetTarget()."
135 "Important Note: As Python code gets collected into functions, access to global \
136 variables requires explicit scoping using the 'global' keyword. Be sure to use correct \
137 Python syntax, including indentation, when entering Python breakpoint commands."
140 Example Python one-line breakpoint command:
142 (lldb) breakpoint command add -s python 1
143 Enter your Python command(s). Type 'DONE' to end.
144 > print "Hit this breakpoint!"
145 > DONE
147 As a convenience, this also works for a short Python one-liner:
149 (lldb) breakpoint command add -s python 1 -o 'import time; print time.asctime()'
150 (lldb) run
151 Launching '.../a.out' (x86_64)
152 (lldb) Fri Sep 10 12:17:45 2010
153 Process 21778 Stopped
154 * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread
156 37 int c(int val)
157 38 {
158 39 -> return val + 3;
159 40 }
161 42 int main (int argc, char const *argv[])
163 Example multiple line Python breakpoint command:
165 (lldb) breakpoint command add -s p 1
166 Enter your Python command(s). Type 'DONE' to end.
167 > global bp_count
168 > bp_count = bp_count + 1
169 > print "Hit this breakpoint " + repr(bp_count) + " times!"
170 > DONE
172 Example multiple line Python breakpoint command, using function definition:
174 (lldb) breakpoint command add -s python 1
175 Enter your Python command(s). Type 'DONE' to end.
176 > def breakpoint_output (bp_no):
177 > out_string = "Hit breakpoint number " + repr (bp_no)
178 > print out_string
179 > return True
180 > breakpoint_output (1)
181 > DONE
184 "In this case, since there is a reference to a global variable, \
185 'bp_count', you will also need to make sure 'bp_count' exists and is \
186 initialized:"
189 (lldb) script
190 >>> bp_count = 0
191 >>> quit()
194 "Your Python code, however organized, can optionally return a value. \
195 If the returned value is False, that tells LLDB not to stop at the breakpoint \
196 to which the code is associated. Returning anything other than False, or even \
197 returning None, or even omitting a return statement entirely, will cause \
198 LLDB to stop."
202 "Final Note: A warning that no breakpoint command was generated when there \
203 are no syntax errors may indicate that a function was declared but never called.");
205 m_all_options.Append(&m_options);
206 m_all_options.Append(&m_func_options, LLDB_OPT_SET_2 | LLDB_OPT_SET_3,
207 LLDB_OPT_SET_2);
208 m_all_options.Finalize();
210 CommandArgumentEntry arg;
211 CommandArgumentData bp_id_arg;
213 // Define the first (and only) variant of this arg.
214 bp_id_arg.arg_type = eArgTypeBreakpointID;
215 bp_id_arg.arg_repetition = eArgRepeatOptional;
217 // There is only one variant this argument could be; put it into the
218 // argument entry.
219 arg.push_back(bp_id_arg);
221 // Push the data for the first argument into the m_arguments vector.
222 m_arguments.push_back(arg);
225 ~CommandObjectBreakpointCommandAdd() override = default;
227 Options *GetOptions() override { return &m_all_options; }
229 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override {
230 StreamFileSP output_sp(io_handler.GetOutputStreamFileSP());
231 if (output_sp && interactive) {
232 output_sp->PutCString(g_reader_instructions);
233 output_sp->Flush();
237 void IOHandlerInputComplete(IOHandler &io_handler,
238 std::string &line) override {
239 io_handler.SetIsDone(true);
241 std::vector<BreakpointOptions *> *bp_options_vec =
242 (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
243 for (BreakpointOptions *bp_options : *bp_options_vec) {
244 if (!bp_options)
245 continue;
247 auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
248 cmd_data->user_source.SplitIntoLines(line.c_str(), line.size());
249 bp_options->SetCommandDataCallback(cmd_data);
253 void CollectDataForBreakpointCommandCallback(
254 std::vector<BreakpointOptions *> &bp_options_vec,
255 CommandReturnObject &result) {
256 m_interpreter.GetLLDBCommandsFromIOHandler(
257 "> ", // Prompt
258 *this, // IOHandlerDelegate
259 &bp_options_vec); // Baton for the "io_handler" that will be passed back
260 // into our IOHandlerDelegate functions
263 /// Set a one-liner as the callback for the breakpoint.
264 void
265 SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec,
266 const char *oneliner) {
267 for (auto bp_options : bp_options_vec) {
268 auto cmd_data = std::make_unique<BreakpointOptions::CommandData>();
270 cmd_data->user_source.AppendString(oneliner);
271 cmd_data->stop_on_error = m_options.m_stop_on_error;
273 bp_options->SetCommandDataCallback(cmd_data);
277 class CommandOptions : public OptionGroup {
278 public:
279 CommandOptions()
280 : OptionGroup(), m_use_commands(false), m_use_script_language(false),
281 m_script_language(eScriptLanguageNone), m_use_one_liner(false),
282 m_one_liner() {}
284 ~CommandOptions() override = default;
286 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
287 ExecutionContext *execution_context) override {
288 Status error;
289 const int short_option =
290 g_breakpoint_command_add_options[option_idx].short_option;
292 switch (short_option) {
293 case 'o':
294 m_use_one_liner = true;
295 m_one_liner = option_arg;
296 break;
298 case 's':
299 m_script_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
300 option_arg,
301 g_breakpoint_command_add_options[option_idx].enum_values,
302 eScriptLanguageNone, error);
303 switch (m_script_language) {
304 case eScriptLanguagePython:
305 case eScriptLanguageLua:
306 m_use_script_language = true;
307 break;
308 case eScriptLanguageNone:
309 case eScriptLanguageUnknown:
310 m_use_script_language = false;
311 break;
313 break;
315 case 'e': {
316 bool success = false;
317 m_stop_on_error =
318 OptionArgParser::ToBoolean(option_arg, false, &success);
319 if (!success)
320 error.SetErrorStringWithFormat(
321 "invalid value for stop-on-error: \"%s\"",
322 option_arg.str().c_str());
323 } break;
325 case 'D':
326 m_use_dummy = true;
327 break;
329 default:
330 llvm_unreachable("Unimplemented option");
332 return error;
335 void OptionParsingStarting(ExecutionContext *execution_context) override {
336 m_use_commands = true;
337 m_use_script_language = false;
338 m_script_language = eScriptLanguageNone;
340 m_use_one_liner = false;
341 m_stop_on_error = true;
342 m_one_liner.clear();
343 m_use_dummy = false;
346 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
347 return llvm::makeArrayRef(g_breakpoint_command_add_options);
350 // Instance variables to hold the values for command options.
352 bool m_use_commands;
353 bool m_use_script_language;
354 lldb::ScriptLanguage m_script_language;
356 // Instance variables to hold the values for one_liner options.
357 bool m_use_one_liner;
358 std::string m_one_liner;
359 bool m_stop_on_error;
360 bool m_use_dummy;
363 protected:
364 bool DoExecute(Args &command, CommandReturnObject &result) override {
365 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
367 const BreakpointList &breakpoints = target.GetBreakpointList();
368 size_t num_breakpoints = breakpoints.GetSize();
370 if (num_breakpoints == 0) {
371 result.AppendError("No breakpoints exist to have commands added");
372 result.SetStatus(eReturnStatusFailed);
373 return false;
376 if (!m_func_options.GetName().empty()) {
377 m_options.m_use_one_liner = false;
378 if (!m_options.m_use_script_language) {
379 m_options.m_script_language = GetDebugger().GetScriptLanguage();
380 m_options.m_use_script_language = true;
384 BreakpointIDList valid_bp_ids;
385 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
386 command, &target, result, &valid_bp_ids,
387 BreakpointName::Permissions::PermissionKinds::listPerm);
389 m_bp_options_vec.clear();
391 if (result.Succeeded()) {
392 const size_t count = valid_bp_ids.GetSize();
394 for (size_t i = 0; i < count; ++i) {
395 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
396 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
397 Breakpoint *bp =
398 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
399 BreakpointOptions *bp_options = nullptr;
400 if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) {
401 // This breakpoint does not have an associated location.
402 bp_options = bp->GetOptions();
403 } else {
404 BreakpointLocationSP bp_loc_sp(
405 bp->FindLocationByID(cur_bp_id.GetLocationID()));
406 // This breakpoint does have an associated location. Get its
407 // breakpoint options.
408 if (bp_loc_sp)
409 bp_options = bp_loc_sp->GetLocationOptions();
411 if (bp_options)
412 m_bp_options_vec.push_back(bp_options);
416 // If we are using script language, get the script interpreter in order
417 // to set or collect command callback. Otherwise, call the methods
418 // associated with this object.
419 if (m_options.m_use_script_language) {
420 ScriptInterpreter *script_interp = GetDebugger().GetScriptInterpreter(
421 /*can_create=*/true, m_options.m_script_language);
422 // Special handling for one-liner specified inline.
423 if (m_options.m_use_one_liner) {
424 script_interp->SetBreakpointCommandCallback(
425 m_bp_options_vec, m_options.m_one_liner.c_str());
426 } else if (!m_func_options.GetName().empty()) {
427 Status error = script_interp->SetBreakpointCommandCallbackFunction(
428 m_bp_options_vec, m_func_options.GetName().c_str(),
429 m_func_options.GetStructuredData());
430 if (!error.Success())
431 result.SetError(error);
432 } else {
433 script_interp->CollectDataForBreakpointCommandCallback(
434 m_bp_options_vec, result);
436 } else {
437 // Special handling for one-liner specified inline.
438 if (m_options.m_use_one_liner)
439 SetBreakpointCommandCallback(m_bp_options_vec,
440 m_options.m_one_liner.c_str());
441 else
442 CollectDataForBreakpointCommandCallback(m_bp_options_vec, result);
446 return result.Succeeded();
449 private:
450 CommandOptions m_options;
451 OptionGroupPythonClassWithDict m_func_options;
452 OptionGroupOptions m_all_options;
454 std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the
455 // breakpoint options that
456 // we are currently
457 // collecting commands for. In the CollectData... calls we need to hand this
458 // off to the IOHandler, which may run asynchronously. So we have to have
459 // some way to keep it alive, and not leak it. Making it an ivar of the
460 // command object, which never goes away achieves this. Note that if we were
461 // able to run the same command concurrently in one interpreter we'd have to
462 // make this "per invocation". But there are many more reasons why it is not
463 // in general safe to do that in lldb at present, so it isn't worthwhile to
464 // come up with a more complex mechanism to address this particular weakness
465 // right now.
466 static const char *g_reader_instructions;
469 const char *CommandObjectBreakpointCommandAdd::g_reader_instructions =
470 "Enter your debugger command(s). Type 'DONE' to end.\n";
472 // CommandObjectBreakpointCommandDelete
474 #define LLDB_OPTIONS_breakpoint_command_delete
475 #include "CommandOptions.inc"
477 class CommandObjectBreakpointCommandDelete : public CommandObjectParsed {
478 public:
479 CommandObjectBreakpointCommandDelete(CommandInterpreter &interpreter)
480 : CommandObjectParsed(interpreter, "delete",
481 "Delete the set of commands from a breakpoint.",
482 nullptr),
483 m_options() {
484 CommandArgumentEntry arg;
485 CommandArgumentData bp_id_arg;
487 // Define the first (and only) variant of this arg.
488 bp_id_arg.arg_type = eArgTypeBreakpointID;
489 bp_id_arg.arg_repetition = eArgRepeatPlain;
491 // There is only one variant this argument could be; put it into the
492 // argument entry.
493 arg.push_back(bp_id_arg);
495 // Push the data for the first argument into the m_arguments vector.
496 m_arguments.push_back(arg);
499 ~CommandObjectBreakpointCommandDelete() override = default;
501 Options *GetOptions() override { return &m_options; }
503 class CommandOptions : public Options {
504 public:
505 CommandOptions() : Options(), m_use_dummy(false) {}
507 ~CommandOptions() override = default;
509 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
510 ExecutionContext *execution_context) override {
511 Status error;
512 const int short_option = m_getopt_table[option_idx].val;
514 switch (short_option) {
515 case 'D':
516 m_use_dummy = true;
517 break;
519 default:
520 llvm_unreachable("Unimplemented option");
523 return error;
526 void OptionParsingStarting(ExecutionContext *execution_context) override {
527 m_use_dummy = false;
530 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
531 return llvm::makeArrayRef(g_breakpoint_command_delete_options);
534 // Instance variables to hold the values for command options.
535 bool m_use_dummy;
538 protected:
539 bool DoExecute(Args &command, CommandReturnObject &result) override {
540 Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
542 const BreakpointList &breakpoints = target.GetBreakpointList();
543 size_t num_breakpoints = breakpoints.GetSize();
545 if (num_breakpoints == 0) {
546 result.AppendError("No breakpoints exist to have commands deleted");
547 result.SetStatus(eReturnStatusFailed);
548 return false;
551 if (command.empty()) {
552 result.AppendError(
553 "No breakpoint specified from which to delete the commands");
554 result.SetStatus(eReturnStatusFailed);
555 return false;
558 BreakpointIDList valid_bp_ids;
559 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
560 command, &target, result, &valid_bp_ids,
561 BreakpointName::Permissions::PermissionKinds::listPerm);
563 if (result.Succeeded()) {
564 const size_t count = valid_bp_ids.GetSize();
565 for (size_t i = 0; i < count; ++i) {
566 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
567 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
568 Breakpoint *bp =
569 target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
570 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
571 BreakpointLocationSP bp_loc_sp(
572 bp->FindLocationByID(cur_bp_id.GetLocationID()));
573 if (bp_loc_sp)
574 bp_loc_sp->ClearCallback();
575 else {
576 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
577 cur_bp_id.GetBreakpointID(),
578 cur_bp_id.GetLocationID());
579 result.SetStatus(eReturnStatusFailed);
580 return false;
582 } else {
583 bp->ClearCallback();
588 return result.Succeeded();
591 private:
592 CommandOptions m_options;
595 // CommandObjectBreakpointCommandList
597 class CommandObjectBreakpointCommandList : public CommandObjectParsed {
598 public:
599 CommandObjectBreakpointCommandList(CommandInterpreter &interpreter)
600 : CommandObjectParsed(interpreter, "list",
601 "List the script or set of commands to be "
602 "executed when the breakpoint is hit.",
603 nullptr, eCommandRequiresTarget) {
604 CommandArgumentEntry arg;
605 CommandArgumentData bp_id_arg;
607 // Define the first (and only) variant of this arg.
608 bp_id_arg.arg_type = eArgTypeBreakpointID;
609 bp_id_arg.arg_repetition = eArgRepeatPlain;
611 // There is only one variant this argument could be; put it into the
612 // argument entry.
613 arg.push_back(bp_id_arg);
615 // Push the data for the first argument into the m_arguments vector.
616 m_arguments.push_back(arg);
619 ~CommandObjectBreakpointCommandList() override = default;
621 protected:
622 bool DoExecute(Args &command, CommandReturnObject &result) override {
623 Target *target = &GetSelectedTarget();
625 const BreakpointList &breakpoints = target->GetBreakpointList();
626 size_t num_breakpoints = breakpoints.GetSize();
628 if (num_breakpoints == 0) {
629 result.AppendError("No breakpoints exist for which to list commands");
630 result.SetStatus(eReturnStatusFailed);
631 return false;
634 if (command.empty()) {
635 result.AppendError(
636 "No breakpoint specified for which to list the commands");
637 result.SetStatus(eReturnStatusFailed);
638 return false;
641 BreakpointIDList valid_bp_ids;
642 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
643 command, target, result, &valid_bp_ids,
644 BreakpointName::Permissions::PermissionKinds::listPerm);
646 if (result.Succeeded()) {
647 const size_t count = valid_bp_ids.GetSize();
648 for (size_t i = 0; i < count; ++i) {
649 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i);
650 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) {
651 Breakpoint *bp =
652 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get();
654 if (bp) {
655 BreakpointLocationSP bp_loc_sp;
656 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) {
657 bp_loc_sp = bp->FindLocationByID(cur_bp_id.GetLocationID());
658 if (!bp_loc_sp) {
659 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
660 cur_bp_id.GetBreakpointID(),
661 cur_bp_id.GetLocationID());
662 result.SetStatus(eReturnStatusFailed);
663 return false;
667 StreamString id_str;
668 BreakpointID::GetCanonicalReference(&id_str,
669 cur_bp_id.GetBreakpointID(),
670 cur_bp_id.GetLocationID());
671 const Baton *baton = nullptr;
672 if (bp_loc_sp)
673 baton =
674 bp_loc_sp
675 ->GetOptionsSpecifyingKind(BreakpointOptions::eCallback)
676 ->GetBaton();
677 else
678 baton = bp->GetOptions()->GetBaton();
680 if (baton) {
681 result.GetOutputStream().Printf("Breakpoint %s:\n",
682 id_str.GetData());
683 baton->GetDescription(result.GetOutputStream().AsRawOstream(),
684 eDescriptionLevelFull,
685 result.GetOutputStream().GetIndentLevel() +
687 } else {
688 result.AppendMessageWithFormat(
689 "Breakpoint %s does not have an associated command.\n",
690 id_str.GetData());
693 result.SetStatus(eReturnStatusSuccessFinishResult);
694 } else {
695 result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n",
696 cur_bp_id.GetBreakpointID());
697 result.SetStatus(eReturnStatusFailed);
702 return result.Succeeded();
706 // CommandObjectBreakpointCommand
708 CommandObjectBreakpointCommand::CommandObjectBreakpointCommand(
709 CommandInterpreter &interpreter)
710 : CommandObjectMultiword(
711 interpreter, "command",
712 "Commands for adding, removing and listing "
713 "LLDB commands executed when a breakpoint is "
714 "hit.",
715 "command <sub-command> [<sub-command-options>] <breakpoint-id>") {
716 CommandObjectSP add_command_object(
717 new CommandObjectBreakpointCommandAdd(interpreter));
718 CommandObjectSP delete_command_object(
719 new CommandObjectBreakpointCommandDelete(interpreter));
720 CommandObjectSP list_command_object(
721 new CommandObjectBreakpointCommandList(interpreter));
723 add_command_object->SetCommandName("breakpoint command add");
724 delete_command_object->SetCommandName("breakpoint command delete");
725 list_command_object->SetCommandName("breakpoint command list");
727 LoadSubCommand("add", add_command_object);
728 LoadSubCommand("delete", delete_command_object);
729 LoadSubCommand("list", list_command_object);
732 CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand() = default;