summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp924
1 files changed, 924 insertions, 0 deletions
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
new file mode 100644
index 0000000..8f8404b
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -0,0 +1,924 @@
+//===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+// C Includes
+// C++ Includes
+
+
+#include "CommandObjectBreakpointCommand.h"
+#include "CommandObjectBreakpoint.h"
+
+#include "lldb/Core/IOHandler.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Breakpoint/BreakpointIDList.h"
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Core/State.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandAdd
+//-------------------------------------------------------------------------
+
+
+class CommandObjectBreakpointCommandAdd :
+ public CommandObjectParsed,
+ public IOHandlerDelegateMultiline
+{
+public:
+
+ CommandObjectBreakpointCommandAdd (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "add",
+ "Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit."
+ " If no breakpoint is specified, adds the commands to the last created breakpoint.",
+ NULL),
+ IOHandlerDelegateMultiline ("DONE", IOHandlerDelegate::Completion::LLDBCommand),
+ m_options (interpreter)
+ {
+ SetHelpLong (
+"\nGeneral information about entering breakpoint commands\n\
+------------------------------------------------------\n\
+\n\
+This command will cause you to be prompted to enter the command or set of\n\
+commands you wish to be executed when the specified breakpoint is hit. You\n\
+will be told to enter your command(s), and will see a '> 'prompt. Because\n\
+you can enter one or many commands to be executed when a breakpoint is hit,\n\
+you will continue to be prompted after each new-line that you enter, until you\n\
+enter the word 'DONE', which will cause the commands you have entered to be\n\
+stored with the breakpoint and executed when the breakpoint is hit.\n\
+\n\
+Syntax checking is not necessarily done when breakpoint commands are entered.\n\
+An improperly written breakpoint command will attempt to get executed when the\n\
+breakpoint gets hit, and usually silently fail. If your breakpoint command does\n\
+not appear to be getting executed, go back and check your syntax.\n\
+\n\
+Special information about PYTHON breakpoint commands\n\
+----------------------------------------------------\n\
+\n\
+You may enter either one line of Python, multiple lines of Python (including\n\
+function definitions), or specify a Python function in a module that has already,\n\
+or will be imported. If you enter a single line of Python, that will be passed\n\
+to the Python interpreter 'as is' when the breakpoint gets hit. If you enter\n\
+function definitions, they will be passed to the Python interpreter as soon as\n\
+you finish entering the breakpoint command, and they can be called later (don't\n\
+forget to add calls to them, if you want them called when the breakpoint is\n\
+hit). If you enter multiple lines of Python that are not function definitions,\n\
+they will be collected into a new, automatically generated Python function, and\n\
+a call to the newly generated function will be attached to the breakpoint.\n\
+\n\
+\n\
+This auto-generated function is passed in three arguments:\n\
+\n\
+ frame: a lldb.SBFrame object for the frame which hit breakpoint.\n\
+ bp_loc: a lldb.SBBreakpointLocation object that represents the breakpoint\n\
+ location that was hit.\n\
+ dict: the python session dictionary hit.\n\
+\n\
+When specifying a python function with the --python-function option, you need\n\
+to supply the function name prepended by the module name. So if you import a\n\
+module named 'myutils' that contains a 'breakpoint_callback' function, you would\n\
+specify the option as:\n\
+\n\
+ --python-function myutils.breakpoint_callback\n\
+\n\
+The function itself must have the following prototype:\n\
+\n\
+def breakpoint_callback(frame, bp_loc, dict):\n\
+ # Your code goes here\n\
+\n\
+The arguments are the same as the 3 auto generation function arguments listed\n\
+above. Note that the global variable 'lldb.frame' will NOT be setup when this\n\
+function is called, so be sure to use the 'frame' argument. The 'frame' argument\n\
+can get you to the thread (frame.GetThread()), the thread can get you to the\n\
+process (thread.GetProcess()), and the process can get you back to the target\n\
+(process.GetTarget()).\n\
+\n\
+Important Note: Because loose Python code gets collected into functions, if you\n\
+want to access global variables in the 'loose' code, you need to specify that\n\
+they are global, using the 'global' keyword. Be sure to use correct Python\n\
+syntax, including indentation, when entering Python breakpoint commands.\n\
+\n\
+As a third option, you can pass the name of an already existing Python function\n\
+and that function will be attached to the breakpoint. It will get passed the\n\
+frame and bp_loc arguments mentioned above.\n\
+\n\
+Example Python one-line breakpoint command:\n\
+\n\
+(lldb) breakpoint command add -s python 1\n\
+Enter your Python command(s). Type 'DONE' to end.\n\
+> print \"Hit this breakpoint!\"\n\
+> DONE\n\
+\n\
+As a convenience, this also works for a short Python one-liner:\n\
+(lldb) breakpoint command add -s python 1 -o \"import time; print time.asctime()\"\n\
+(lldb) run\n\
+Launching '.../a.out' (x86_64)\n\
+(lldb) Fri Sep 10 12:17:45 2010\n\
+Process 21778 Stopped\n\
+* thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread\n\
+ 36 \n\
+ 37 int c(int val)\n\
+ 38 {\n\
+ 39 -> return val + 3;\n\
+ 40 }\n\
+ 41 \n\
+ 42 int main (int argc, char const *argv[])\n\
+(lldb)\n\
+\n\
+Example multiple line Python breakpoint command, using function definition:\n\
+\n\
+(lldb) breakpoint command add -s python 1\n\
+Enter your Python command(s). Type 'DONE' to end.\n\
+> def breakpoint_output (bp_no):\n\
+> out_string = \"Hit breakpoint number \" + repr (bp_no)\n\
+> print out_string\n\
+> return True\n\
+> breakpoint_output (1)\n\
+> DONE\n\
+\n\
+\n\
+Example multiple line Python breakpoint command, using 'loose' Python:\n\
+\n\
+(lldb) breakpoint command add -s p 1\n\
+Enter your Python command(s). Type 'DONE' to end.\n\
+> global bp_count\n\
+> bp_count = bp_count + 1\n\
+> print \"Hit this breakpoint \" + repr(bp_count) + \" times!\"\n\
+> DONE\n\
+\n\
+In this case, since there is a reference to a global variable,\n\
+'bp_count', you will also need to make sure 'bp_count' exists and is\n\
+initialized:\n\
+\n\
+(lldb) script\n\
+>>> bp_count = 0\n\
+>>> quit()\n\
+\n\
+(lldb)\n\
+\n\
+\n\
+Your Python code, however organized, can optionally return a value.\n\
+If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
+to which the code is associated. Returning anything other than False, or even\n\
+returning None, or even omitting a return statement entirely, will cause\n\
+LLDB to stop.\n\
+\n\
+Final Note: If you get a warning that no breakpoint command was generated, but\n\
+you did not get any syntax errors, you probably forgot to add a call to your\n\
+functions.\n\
+\n\
+Special information about debugger command breakpoint commands\n\
+--------------------------------------------------------------\n\
+\n\
+You may enter any debugger command, exactly as you would at the debugger prompt.\n\
+You may enter as many debugger commands as you like, but do NOT enter more than\n\
+one command per line.\n" );
+
+ CommandArgumentEntry arg;
+ CommandArgumentData bp_id_arg;
+
+ // Define the first (and only) variant of this arg.
+ bp_id_arg.arg_type = eArgTypeBreakpointID;
+ bp_id_arg.arg_repetition = eArgRepeatOptional;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg.push_back (bp_id_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg);
+ }
+
+ virtual
+ ~CommandObjectBreakpointCommandAdd () {}
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ virtual void
+ IOHandlerActivated (IOHandler &io_handler)
+ {
+ StreamFileSP output_sp(io_handler.GetOutputStreamFile());
+ if (output_sp)
+ {
+ output_sp->PutCString(g_reader_instructions);
+ output_sp->Flush();
+ }
+ }
+
+
+ virtual void
+ IOHandlerInputComplete (IOHandler &io_handler, std::string &line)
+ {
+ io_handler.SetIsDone(true);
+
+ std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
+ for (BreakpointOptions *bp_options : *bp_options_vec)
+ {
+ if (!bp_options)
+ continue;
+
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ if (data_ap.get())
+ {
+ data_ap->user_source.SplitIntoLines (line.c_str(), line.size());
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
+ }
+ }
+ }
+
+ void
+ CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
+ CommandReturnObject &result)
+ {
+ m_interpreter.GetLLDBCommandsFromIOHandler ("> ", // Prompt
+ *this, // IOHandlerDelegate
+ true, // Run IOHandler in async mode
+ &bp_options_vec); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+ }
+
+ /// Set a one-liner as the callback for the breakpoint.
+ void
+ SetBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
+ const char *oneliner)
+ {
+ for (auto bp_options : bp_options_vec)
+ {
+ std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+
+ // It's necessary to set both user_source and script_source to the oneliner.
+ // The former is used to generate callback description (as in breakpoint command list)
+ // while the latter is used for Python to interpret during the actual callback.
+ data_ap->user_source.AppendString (oneliner);
+ data_ap->script_source.assign (oneliner);
+ data_ap->stop_on_error = m_options.m_stop_on_error;
+
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (BreakpointOptionsCallbackFunction, baton_sp);
+ }
+ return;
+ }
+
+ static bool
+ BreakpointOptionsCallbackFunction (void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id)
+ {
+ bool ret_value = true;
+ if (baton == NULL)
+ return true;
+
+
+ BreakpointOptions::CommandData *data = (BreakpointOptions::CommandData *) baton;
+ StringList &commands = data->user_source;
+
+ if (commands.GetSize() > 0)
+ {
+ ExecutionContext exe_ctx (context->exe_ctx_ref);
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ {
+ CommandReturnObject result;
+ Debugger &debugger = target->GetDebugger();
+ // Rig up the results secondary output stream to the debugger's, so the output will come out synchronously
+ // if the debugger is set up that way.
+
+ StreamSP output_stream (debugger.GetAsyncOutputStream());
+ StreamSP error_stream (debugger.GetAsyncErrorStream());
+ result.SetImmediateOutputStream (output_stream);
+ result.SetImmediateErrorStream (error_stream);
+
+ CommandInterpreterRunOptions options;
+ options.SetStopOnContinue(true);
+ options.SetStopOnError (data->stop_on_error);
+ options.SetEchoCommands (true);
+ options.SetPrintResults (true);
+ options.SetAddToHistory (false);
+
+ debugger.GetCommandInterpreter().HandleCommands (commands,
+ &exe_ctx,
+ options,
+ result);
+ result.GetImmediateOutputStream()->Flush();
+ result.GetImmediateErrorStream()->Flush();
+ }
+ }
+ return ret_value;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter),
+ m_use_commands (false),
+ m_use_script_language (false),
+ m_script_language (eScriptLanguageNone),
+ m_use_one_liner (false),
+ m_one_liner(),
+ m_function_name()
+ {
+ }
+
+ virtual
+ ~CommandOptions () {}
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'o':
+ m_use_one_liner = true;
+ m_one_liner = option_arg;
+ break;
+
+ case 's':
+ m_script_language = (lldb::ScriptLanguage) Args::StringToOptionEnum (option_arg,
+ g_option_table[option_idx].enum_values,
+ eScriptLanguageNone,
+ error);
+
+ if (m_script_language == eScriptLanguagePython || m_script_language == eScriptLanguageDefault)
+ {
+ m_use_script_language = true;
+ }
+ else
+ {
+ m_use_script_language = false;
+ }
+ break;
+
+ case 'e':
+ {
+ bool success = false;
+ m_stop_on_error = Args::StringToBoolean(option_arg, false, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("invalid value for stop-on-error: \"%s\"", option_arg);
+ }
+ break;
+
+ case 'F':
+ {
+ m_use_one_liner = false;
+ m_use_script_language = true;
+ m_function_name.assign(option_arg);
+ }
+ break;
+
+ case 'D':
+ m_use_dummy = true;
+ break;
+
+ default:
+ break;
+ }
+ return error;
+ }
+ void
+ OptionParsingStarting ()
+ {
+ m_use_commands = true;
+ m_use_script_language = false;
+ m_script_language = eScriptLanguageNone;
+
+ m_use_one_liner = false;
+ m_stop_on_error = true;
+ m_one_liner.clear();
+ m_function_name.clear();
+ m_use_dummy = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ bool m_use_commands;
+ bool m_use_script_language;
+ lldb::ScriptLanguage m_script_language;
+
+ // Instance variables to hold the values for one_liner options.
+ bool m_use_one_liner;
+ std::string m_one_liner;
+ bool m_stop_on_error;
+ std::string m_function_name;
+ bool m_use_dummy;
+ };
+
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
+
+ if (target == NULL)
+ {
+ result.AppendError ("There is not a current executable; there are no breakpoints to which to add commands");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const BreakpointList &breakpoints = target->GetBreakpointList();
+ size_t num_breakpoints = breakpoints.GetSize();
+
+ if (num_breakpoints == 0)
+ {
+ result.AppendError ("No breakpoints exist to have commands added");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (m_options.m_use_script_language == false && m_options.m_function_name.size())
+ {
+ result.AppendError ("need to enable scripting to have a function run as a breakpoint command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
+
+ m_bp_options_vec.clear();
+
+ if (result.Succeeded())
+ {
+ const size_t count = valid_bp_ids.GetSize();
+
+ for (size_t i = 0; i < count; ++i)
+ {
+ BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+ if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+ {
+ Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+ BreakpointOptions *bp_options = NULL;
+ if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
+ {
+ // This breakpoint does not have an associated location.
+ bp_options = bp->GetOptions();
+ }
+ else
+ {
+ BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
+ // This breakpoint does have an associated location.
+ // Get its breakpoint options.
+ if (bp_loc_sp)
+ bp_options = bp_loc_sp->GetLocationOptions();
+ }
+ if (bp_options)
+ m_bp_options_vec.push_back (bp_options);
+ }
+ }
+
+ // If we are using script language, get the script interpreter
+ // in order to set or collect command callback. Otherwise, call
+ // the methods associated with this object.
+ if (m_options.m_use_script_language)
+ {
+ ScriptInterpreter *script_interp = m_interpreter.GetScriptInterpreter();
+ // Special handling for one-liner specified inline.
+ if (m_options.m_use_one_liner)
+ {
+ script_interp->SetBreakpointCommandCallback (m_bp_options_vec,
+ m_options.m_one_liner.c_str());
+ }
+ else if (m_options.m_function_name.size())
+ {
+ script_interp->SetBreakpointCommandCallbackFunction (m_bp_options_vec,
+ m_options.m_function_name.c_str());
+ }
+ else
+ {
+ script_interp->CollectDataForBreakpointCommandCallback (m_bp_options_vec,
+ result);
+ }
+ }
+ else
+ {
+ // Special handling for one-liner specified inline.
+ if (m_options.m_use_one_liner)
+ SetBreakpointCommandCallback (m_bp_options_vec,
+ m_options.m_one_liner.c_str());
+ else
+ CollectDataForBreakpointCommandCallback (m_bp_options_vec,
+ result);
+ }
+
+ }
+
+ return result.Succeeded();
+ }
+
+private:
+ CommandOptions m_options;
+ std::vector<BreakpointOptions *> m_bp_options_vec; // This stores the breakpoint options that we are currently
+ // collecting commands for. In the CollectData... calls we need
+ // to hand this off to the IOHandler, which may run asynchronously.
+ // So we have to have some way to keep it alive, and not leak it.
+ // Making it an ivar of the command object, which never goes away
+ // achieves this. Note that if we were able to run
+ // the same command concurrently in one interpreter we'd have to
+ // make this "per invocation". But there are many more reasons
+ // why it is not in general safe to do that in lldb at present,
+ // so it isn't worthwhile to come up with a more complex mechanism
+ // to address this particular weakness right now.
+ static const char *g_reader_instructions;
+
+};
+
+const char *
+CommandObjectBreakpointCommandAdd::g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.\n";
+
+// FIXME: "script-type" needs to have its contents determined dynamically, so somebody can add a new scripting
+// language to lldb and have it pickable here without having to change this enumeration by hand and rebuild lldb proper.
+
+static OptionEnumValueElement
+g_script_option_enumeration[4] =
+{
+ { eScriptLanguageNone, "command", "Commands are in the lldb command interpreter language"},
+ { eScriptLanguagePython, "python", "Commands are in the Python language."},
+ { eSortOrderByName, "default-script", "Commands are in the default scripting language."},
+ { 0, NULL, NULL }
+};
+
+OptionDefinition
+CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOneLiner,
+ "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." },
+
+ { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeBoolean,
+ "Specify whether breakpoint command execution should terminate on error." },
+
+ { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, NULL, g_script_option_enumeration, 0, eArgTypeNone,
+ "Specify the language for the commands - if none is specified, the lldb command interpreter will be used."},
+
+ { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, NULL, NULL, 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."},
+
+ { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointCommandDelete : public CommandObjectParsed
+{
+public:
+ CommandObjectBreakpointCommandDelete (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "delete",
+ "Delete the set of commands from a breakpoint.",
+ NULL),
+ m_options (interpreter)
+ {
+ CommandArgumentEntry arg;
+ CommandArgumentData bp_id_arg;
+
+ // Define the first (and only) variant of this arg.
+ bp_id_arg.arg_type = eArgTypeBreakpointID;
+ bp_id_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg.push_back (bp_id_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg);
+ }
+
+
+ virtual
+ ~CommandObjectBreakpointCommandDelete () {}
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions (CommandInterpreter &interpreter) :
+ Options (interpreter),
+ m_use_dummy (false)
+ {
+ }
+
+ virtual
+ ~CommandOptions () {}
+
+ virtual Error
+ SetOptionValue (uint32_t option_idx, const char *option_arg)
+ {
+ Error error;
+ const int short_option = m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'D':
+ m_use_dummy = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ OptionParsingStarting ()
+ {
+ m_use_dummy = false;
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ bool m_use_dummy;
+ };
+
+protected:
+ virtual bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+ Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy);
+
+ if (target == NULL)
+ {
+ result.AppendError ("There is not a current executable; there are no breakpoints from which to delete commands");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const BreakpointList &breakpoints = target->GetBreakpointList();
+ size_t num_breakpoints = breakpoints.GetSize();
+
+ if (num_breakpoints == 0)
+ {
+ result.AppendError ("No breakpoints exist to have commands deleted");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (command.GetArgumentCount() == 0)
+ {
+ result.AppendError ("No breakpoint specified from which to delete the commands");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ const size_t count = valid_bp_ids.GetSize();
+ for (size_t i = 0; i < count; ++i)
+ {
+ BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+ if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+ {
+ Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+ if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+ {
+ BreakpointLocationSP bp_loc_sp (bp->FindLocationByID (cur_bp_id.GetLocationID()));
+ if (bp_loc_sp)
+ bp_loc_sp->ClearCallback();
+ else
+ {
+ result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
+ cur_bp_id.GetBreakpointID(),
+ cur_bp_id.GetLocationID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ bp->ClearCallback();
+ }
+ }
+ }
+ }
+ return result.Succeeded();
+ }
+private:
+ CommandOptions m_options;
+};
+
+OptionDefinition
+CommandObjectBreakpointCommandDelete::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
+ "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."},
+
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandList
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointCommandList : public CommandObjectParsed
+{
+public:
+ CommandObjectBreakpointCommandList (CommandInterpreter &interpreter) :
+ CommandObjectParsed (interpreter,
+ "list",
+ "List the script or set of commands to be executed when the breakpoint is hit.",
+ NULL)
+ {
+ CommandArgumentEntry arg;
+ CommandArgumentData bp_id_arg;
+
+ // Define the first (and only) variant of this arg.
+ bp_id_arg.arg_type = eArgTypeBreakpointID;
+ bp_id_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg.push_back (bp_id_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg);
+ }
+
+ virtual
+ ~CommandObjectBreakpointCommandList () {}
+
+protected:
+ virtual bool
+ DoExecute (Args& command,
+ CommandReturnObject &result)
+ {
+ Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
+
+ if (target == NULL)
+ {
+ result.AppendError ("There is not a current executable; there are no breakpoints for which to list commands");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const BreakpointList &breakpoints = target->GetBreakpointList();
+ size_t num_breakpoints = breakpoints.GetSize();
+
+ if (num_breakpoints == 0)
+ {
+ result.AppendError ("No breakpoints exist for which to list commands");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (command.GetArgumentCount() == 0)
+ {
+ result.AppendError ("No breakpoint specified for which to list the commands");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ const size_t count = valid_bp_ids.GetSize();
+ for (size_t i = 0; i < count; ++i)
+ {
+ BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+ if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+ {
+ Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+
+ if (bp)
+ {
+ const BreakpointOptions *bp_options = NULL;
+ if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+ {
+ BreakpointLocationSP bp_loc_sp(bp->FindLocationByID (cur_bp_id.GetLocationID()));
+ if (bp_loc_sp)
+ bp_options = bp_loc_sp->GetOptionsNoCreate();
+ else
+ {
+ result.AppendErrorWithFormat("Invalid breakpoint ID: %u.%u.\n",
+ cur_bp_id.GetBreakpointID(),
+ cur_bp_id.GetLocationID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ bp_options = bp->GetOptions();
+ }
+
+ if (bp_options)
+ {
+ StreamString id_str;
+ BreakpointID::GetCanonicalReference (&id_str,
+ cur_bp_id.GetBreakpointID(),
+ cur_bp_id.GetLocationID());
+ const Baton *baton = bp_options->GetBaton();
+ if (baton)
+ {
+ result.GetOutputStream().Printf ("Breakpoint %s:\n", id_str.GetData());
+ result.GetOutputStream().IndentMore ();
+ baton->GetDescription(&result.GetOutputStream(), eDescriptionLevelFull);
+ result.GetOutputStream().IndentLess ();
+ }
+ else
+ {
+ result.AppendMessageWithFormat ("Breakpoint %s does not have an associated command.\n",
+ id_str.GetData());
+ }
+ }
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Invalid breakpoint ID: %u.\n", cur_bp_id.GetBreakpointID());
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ }
+ }
+ }
+
+ return result.Succeeded();
+ }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommand
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointCommand::CommandObjectBreakpointCommand (CommandInterpreter &interpreter) :
+ CommandObjectMultiword (interpreter,
+ "command",
+ "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commands').",
+ "command <sub-command> [<sub-command-options>] <breakpoint-id>")
+{
+ CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd (interpreter));
+ CommandObjectSP delete_command_object (new CommandObjectBreakpointCommandDelete (interpreter));
+ CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList (interpreter));
+
+ add_command_object->SetCommandName ("breakpoint command add");
+ delete_command_object->SetCommandName ("breakpoint command delete");
+ list_command_object->SetCommandName ("breakpoint command list");
+
+ LoadSubCommand ("add", add_command_object);
+ LoadSubCommand ("delete", delete_command_object);
+ LoadSubCommand ("list", list_command_object);
+}
+
+CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
+{
+}
+
+
OpenPOWER on IntegriCloud