summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp')
-rw-r--r--contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp435
1 files changed, 309 insertions, 126 deletions
diff --git a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
index f98eac0..f56d089 100644
--- a/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/contrib/llvm/tools/lldb/source/Commands/CommandObjectCommands.cpp
@@ -7,8 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "lldb/lldb-python.h"
-
#include "CommandObjectCommands.h"
// C Includes
@@ -29,7 +27,6 @@
#include "lldb/Interpreter/OptionValueUInt64.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
-#include "lldb/Interpreter/ScriptInterpreterPython.h"
using namespace lldb;
using namespace lldb_private;
@@ -85,7 +82,7 @@ protected:
switch (short_option)
{
case 'c':
- error = m_count.SetValueFromCString(option_arg,eVarSetOperationAssign);
+ error = m_count.SetValueFromString(option_arg,eVarSetOperationAssign);
break;
case 's':
if (option_arg && strcmp("end", option_arg) == 0)
@@ -94,10 +91,10 @@ protected:
m_start_idx.SetOptionWasSet();
}
else
- error = m_start_idx.SetValueFromCString(option_arg,eVarSetOperationAssign);
+ error = m_start_idx.SetValueFromString(option_arg,eVarSetOperationAssign);
break;
case 'e':
- error = m_stop_idx.SetValueFromCString(option_arg,eVarSetOperationAssign);
+ error = m_stop_idx.SetValueFromString(option_arg,eVarSetOperationAssign);
break;
case 'C':
m_clear.SetCurrentValue(true);
@@ -326,15 +323,15 @@ protected:
switch (short_option)
{
case 'e':
- error = m_stop_on_error.SetValueFromCString(option_arg);
+ error = m_stop_on_error.SetValueFromString(option_arg);
break;
case 'c':
- error = m_stop_on_continue.SetValueFromCString(option_arg);
+ error = m_stop_on_continue.SetValueFromString(option_arg);
break;
case 's':
- error = m_silent_run.SetValueFromCString(option_arg);
+ error = m_silent_run.SetValueFromString(option_arg);
break;
default:
@@ -453,60 +450,74 @@ public:
NULL)
{
SetHelpLong(
- "'alias' allows the user to create a short-cut or abbreviation for long \n\
- commands, multi-word commands, and commands that take particular options. \n\
- Below are some simple examples of how one might use the 'alias' command: \n\
- \n 'command alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
- // command. \n\
- 'command alias bp breakpoint' // Creates the abbreviation 'bp' for the 'breakpoint' \n\
- // command. Since breakpoint commands are two-word \n\
- // commands, the user will still need to enter the \n\
- // second word after 'bp', e.g. 'bp enable' or \n\
- // 'bp delete'. \n\
- 'command alias bpl breakpoint list' // Creates the abbreviation 'bpl' for the \n\
- // two-word command 'breakpoint list'. \n\
- \nAn alias can include some options for the command, with the values either \n\
- filled in at the time the alias is created, or specified as positional \n\
- arguments, to be filled in when the alias is invoked. The following example \n\
- shows how to create aliases with options: \n\
- \n\
- 'command alias bfl breakpoint set -f %1 -l %2' \n\
- \nThis creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \n\
- options already part of the alias. So if the user wants to set a breakpoint \n\
- by file and line without explicitly having to use the -f and -l options, the \n\
- user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \n\
- for the actual arguments that will be passed when the alias command is used. \n\
- The number in the placeholder refers to the position/order the actual value \n\
- occupies when the alias is used. All the occurrences of '%1' in the alias \n\
- will be replaced with the first argument, all the occurrences of '%2' in the \n\
- alias will be replaced with the second argument, and so on. This also allows \n\
- actual arguments to be used multiple times within an alias (see 'process \n\
- launch' example below). \n\
- Note: the positional arguments must substitute as whole words in the resultant\n\
- command, so you can't at present do something like:\n\
- \n\
- command alias bcppfl breakpoint set -f %1.cpp -l %2\n\
- \n\
- to get the file extension \".cpp\" automatically appended. For more complex\n\
- aliasing, use the \"command regex\" command instead.\n\
- \nSo in the 'bfl' case, the actual file value will be \n\
- filled in with the first argument following 'bfl' and the actual line number \n\
- value will be filled in with the second argument. The user would use this \n\
- alias as follows: \n\
- \n (lldb) command alias bfl breakpoint set -f %1 -l %2 \n\
- <... some time later ...> \n\
- (lldb) bfl my-file.c 137 \n\
- \nThis would be the same as if the user had entered \n\
- 'breakpoint set -f my-file.c -l 137'. \n\
- \nAnother example: \n\
- \n (lldb) command alias pltty process launch -s -o %1 -e %1 \n\
- (lldb) pltty /dev/tty0 \n\
- // becomes 'process launch -s -o /dev/tty0 -e /dev/tty0' \n\
- \nIf the user always wanted to pass the same value to a particular option, the \n\
- alias could be defined with that value directly in the alias as a constant, \n\
- rather than using a positional placeholder: \n\
- \n command alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
- // 3 of whatever file is indicated. \n");
+"'alias' allows the user to create a short-cut or abbreviation for long \
+commands, multi-word commands, and commands that take particular options. \
+Below are some simple examples of how one might use the 'alias' command:" R"(
+
+(lldb) command alias sc script
+
+ Creates the abbreviation 'sc' for the 'script' command.
+
+(lldb) command alias bp breakpoint
+
+)" " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \
+breakpoint commands are two-word commands, the user would still need to \
+enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." R"(
+
+(lldb) command alias bpl breakpoint list
+
+ Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'.
+
+)" "An alias can include some options for the command, with the values either \
+filled in at the time the alias is created, or specified as positional \
+arguments, to be filled in when the alias is invoked. The following example \
+shows how to create aliases with options:" R"(
+
+(lldb) command alias bfl breakpoint set -f %1 -l %2
+
+)" " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \
+options already part of the alias. So if the user wants to set a breakpoint \
+by file and line without explicitly having to use the -f and -l options, the \
+user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \
+for the actual arguments that will be passed when the alias command is used. \
+The number in the placeholder refers to the position/order the actual value \
+occupies when the alias is used. All the occurrences of '%1' in the alias \
+will be replaced with the first argument, all the occurrences of '%2' in the \
+alias will be replaced with the second argument, and so on. This also allows \
+actual arguments to be used multiple times within an alias (see 'process \
+launch' example below)." R"(
+
+)" "Note: the positional arguments must substitute as whole words in the resultant \
+command, so you can't at present do something like this to append the file extension \
+\".cpp\":" R"(
+
+(lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2
+
+)" "For more complex aliasing, use the \"command regex\" command instead. In the \
+'bfl' case above, the actual file value will be filled in with the first argument \
+following 'bfl' and the actual line number value will be filled in with the second \
+argument. The user would use this alias as follows:" R"(
+
+(lldb) command alias bfl breakpoint set -f %1 -l %2
+(lldb) bfl my-file.c 137
+
+This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'.
+
+Another example:
+
+(lldb) command alias pltty process launch -s -o %1 -e %1
+(lldb) pltty /dev/tty0
+
+ Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0'
+
+)" "If the user always wanted to pass the same value to a particular option, the \
+alias could be defined with that value directly in the alias as a constant, \
+rather than using a positional placeholder:" R"(
+
+(lldb) command alias bl3 breakpoint set -f %1 -l 3
+
+ Always sets a breakpoint on line 3 of whatever file is indicated.)"
+ );
CommandArgumentEntry arg1;
CommandArgumentEntry arg2;
@@ -963,31 +974,30 @@ public:
IOHandlerDelegateMultiline ("", IOHandlerDelegate::Completion::LLDBCommand),
m_options (interpreter)
{
- SetHelpLong(
-"This command allows the user to create powerful regular expression commands\n"
-"with substitutions. The regular expressions and substitutions are specified\n"
-"using the regular expression substitution format of:\n"
-"\n"
-" s/<regex>/<subst>/\n"
-"\n"
-"<regex> is a regular expression that can use parenthesis to capture regular\n"
-"expression input and substitute the captured matches in the output using %1\n"
-"for the first match, %2 for the second, and so on.\n"
-"\n"
-"The regular expressions can all be specified on the command line if more than\n"
-"one argument is provided. If just the command name is provided on the command\n"
-"line, then the regular expressions and substitutions can be entered on separate\n"
-" lines, followed by an empty line to terminate the command definition.\n"
-"\n"
-"EXAMPLES\n"
-"\n"
-"The following example will define a regular expression command named 'f' that\n"
-"will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if\n"
-"a number follows 'f':\n"
-"\n"
-" (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/'\n"
-"\n"
- );
+ SetHelpLong(R"(
+)" "This command allows the user to create powerful regular expression commands \
+with substitutions. The regular expressions and substitutions are specified \
+using the regular expression substitution format of:" R"(
+
+ s/<regex>/<subst>/
+
+)" "<regex> is a regular expression that can use parenthesis to capture regular \
+expression input and substitute the captured matches in the output using %1 \
+for the first match, %2 for the second, and so on." R"(
+
+)" "The regular expressions can all be specified on the command line if more than \
+one argument is provided. If just the command name is provided on the command \
+line, then the regular expressions and substitutions can be entered on separate \
+lines, followed by an empty line to terminate the command definition." R"(
+
+EXAMPLES
+
+)" "The following example will define a regular expression command named 'f' that \
+will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \
+a number follows 'f':" R"(
+
+ (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"
+ );
}
~CommandObjectCommandsAddRegex()
@@ -1430,6 +1440,130 @@ protected:
};
+class CommandObjectScriptingObject : public CommandObjectRaw
+{
+private:
+ StructuredData::GenericSP m_cmd_obj_sp;
+ ScriptedCommandSynchronicity m_synchro;
+ bool m_fetched_help_short:1;
+ bool m_fetched_help_long:1;
+
+public:
+
+ CommandObjectScriptingObject (CommandInterpreter &interpreter,
+ std::string name,
+ StructuredData::GenericSP cmd_obj_sp,
+ ScriptedCommandSynchronicity synch) :
+ CommandObjectRaw (interpreter,
+ name.c_str(),
+ NULL,
+ NULL),
+ m_cmd_obj_sp(cmd_obj_sp),
+ m_synchro(synch),
+ m_fetched_help_short(false),
+ m_fetched_help_long(false)
+ {
+ StreamString stream;
+ stream.Printf("For more information run 'help %s'",name.c_str());
+ SetHelp(stream.GetData());
+ if (ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter())
+ GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp));
+ }
+
+ virtual
+ ~CommandObjectScriptingObject ()
+ {
+ }
+
+ virtual bool
+ IsRemovable () const
+ {
+ return true;
+ }
+
+ StructuredData::GenericSP
+ GetImplementingObject ()
+ {
+ return m_cmd_obj_sp;
+ }
+
+ ScriptedCommandSynchronicity
+ GetSynchronicity ()
+ {
+ return m_synchro;
+ }
+
+ virtual const char *
+ GetHelp ()
+ {
+ if (!m_fetched_help_short)
+ {
+ ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
+ if (scripter)
+ {
+ std::string docstring;
+ m_fetched_help_short = scripter->GetShortHelpForCommandObject(m_cmd_obj_sp,docstring);
+ if (!docstring.empty())
+ SetHelp(docstring);
+ }
+ }
+ return CommandObjectRaw::GetHelp();
+ }
+
+ virtual const char *
+ GetHelpLong ()
+ {
+ if (!m_fetched_help_long)
+ {
+ ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
+ if (scripter)
+ {
+ std::string docstring;
+ m_fetched_help_long = scripter->GetLongHelpForCommandObject(m_cmd_obj_sp,docstring);
+ if (!docstring.empty())
+ SetHelpLong(docstring);
+ }
+ }
+ return CommandObjectRaw::GetHelpLong();
+ }
+
+protected:
+ virtual bool
+ DoExecute (const char *raw_command_line, CommandReturnObject &result)
+ {
+ ScriptInterpreter* scripter = m_interpreter.GetScriptInterpreter();
+
+ Error error;
+
+ result.SetStatus(eReturnStatusInvalid);
+
+ if (!scripter || scripter->RunScriptBasedCommand(m_cmd_obj_sp,
+ raw_command_line,
+ m_synchro,
+ result,
+ error,
+ m_exe_ctx) == false)
+ {
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ }
+ else
+ {
+ // Don't change the status if the command already set it...
+ if (result.GetStatus() == eReturnStatusInvalid)
+ {
+ if (result.GetOutputData() == NULL || result.GetOutputData()[0] == '\0')
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ else
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+ }
+
+ return result.Succeeded();
+ }
+
+};
+
//-------------------------------------------------------------------------
// CommandObjectCommandsScriptImport
//-------------------------------------------------------------------------
@@ -1449,7 +1583,7 @@ public:
// Define the first (and only) variant of this arg.
cmd_arg.arg_type = eArgTypeFilename;
- cmd_arg.arg_repetition = eArgRepeatPlain;
+ cmd_arg.arg_repetition = eArgRepeatPlus;
// There is only one variant this argument could be; put it into the argument entry.
arg1.push_back (cmd_arg);
@@ -1549,7 +1683,6 @@ protected:
bool
DoExecute (Args& command, CommandReturnObject &result)
{
-
if (m_interpreter.GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython)
{
result.AppendError ("only scripting language supported for module importing is currently Python");
@@ -1558,36 +1691,40 @@ protected:
}
size_t argc = command.GetArgumentCount();
-
- if (argc != 1)
+ if (0 == argc)
{
- result.AppendError ("'command script import' requires one argument");
+ result.AppendError("command script import needs one or more arguments");
result.SetStatus (eReturnStatusFailed);
return false;
}
- std::string path = command.GetArgumentAtIndex(0);
- Error error;
-
- const bool init_session = true;
- // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that
- // commands won't ever be recursively invoked, but it's actually possible to craft
- // a Python script that does other "command script imports" in __lldb_init_module
- // the real fix is to have recursive commands possible with a CommandInvocation object
- // separate from the CommandObject itself, so that recursive command invocations
- // won't stomp on each other (wrt to execution contents, options, and more)
- m_exe_ctx.Clear();
- if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
- m_options.m_allow_reload,
- init_session,
- error))
- {
- result.SetStatus (eReturnStatusSuccessFinishNoResult);
- }
- else
+ for (size_t i = 0;
+ i < argc;
+ i++)
{
- result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
- result.SetStatus (eReturnStatusFailed);
+ std::string path = command.GetArgumentAtIndex(i);
+ Error error;
+
+ const bool init_session = true;
+ // FIXME: this is necessary because CommandObject::CheckRequirements() assumes that
+ // commands won't ever be recursively invoked, but it's actually possible to craft
+ // a Python script that does other "command script imports" in __lldb_init_module
+ // the real fix is to have recursive commands possible with a CommandInvocation object
+ // separate from the CommandObject itself, so that recursive command invocations
+ // won't stomp on each other (wrt to execution contents, options, and more)
+ m_exe_ctx.Clear();
+ if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
+ m_options.m_allow_reload,
+ init_session,
+ error))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat("module importing failed: %s", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
}
return result.Succeeded();
@@ -1652,7 +1789,11 @@ protected:
public:
CommandOptions (CommandInterpreter &interpreter) :
- Options (interpreter)
+ Options (interpreter),
+ m_class_name(),
+ m_funct_name(),
+ m_short_help(),
+ m_synchronicity(eScriptedCommandSynchronicitySynchronous)
{
}
@@ -1671,6 +1812,10 @@ protected:
if (option_arg)
m_funct_name.assign(option_arg);
break;
+ case 'c':
+ if (option_arg)
+ m_class_name.assign(option_arg);
+ break;
case 'h':
if (option_arg)
m_short_help.assign(option_arg);
@@ -1691,6 +1836,7 @@ protected:
void
OptionParsingStarting ()
{
+ m_class_name.clear();
m_funct_name.clear();
m_short_help.clear();
m_synchronicity = eScriptedCommandSynchronicitySynchronous;
@@ -1708,6 +1854,7 @@ protected:
// Instance variables to hold the values for command options.
+ std::string m_class_name;
std::string m_funct_name;
std::string m_short_help;
ScriptedCommandSynchronicity m_synchronicity;
@@ -1812,20 +1959,55 @@ protected:
m_short_help.assign(m_options.m_short_help);
m_synchronicity = m_options.m_synchronicity;
- if (m_options.m_funct_name.empty())
+ if (m_options.m_class_name.empty())
{
- m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt
- *this, // IOHandlerDelegate
- true, // Run IOHandler in async mode
- NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+ if (m_options.m_funct_name.empty())
+ {
+ m_interpreter.GetPythonCommandsFromIOHandler (" ", // Prompt
+ *this, // IOHandlerDelegate
+ true, // Run IOHandler in async mode
+ NULL); // Baton for the "io_handler" that will be passed back into our IOHandlerDelegate functions
+ }
+ else
+ {
+ CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
+ m_cmd_name,
+ m_options.m_funct_name,
+ m_options.m_short_help,
+ m_synchronicity));
+ if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError("cannot add command");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
}
else
{
- CommandObjectSP new_cmd(new CommandObjectPythonFunction(m_interpreter,
- m_cmd_name,
- m_options.m_funct_name,
- m_options.m_short_help,
- m_synchronicity));
+ ScriptInterpreter *interpreter = GetCommandInterpreter().GetScriptInterpreter();
+ if (!interpreter)
+ {
+ result.AppendError("cannot find ScriptInterpreter");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ auto cmd_obj_sp = interpreter->CreateScriptCommandObject(m_options.m_class_name.c_str());
+ if (!cmd_obj_sp)
+ {
+ result.AppendError("cannot create helper object");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ CommandObjectSP new_cmd(new CommandObjectScriptingObject(m_interpreter,
+ m_cmd_name,
+ cmd_obj_sp,
+ m_synchronicity));
if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true))
{
result.SetStatus (eReturnStatusSuccessFinishNoResult);
@@ -1859,8 +2041,9 @@ OptionDefinition
CommandObjectCommandsScriptAdd::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name."},
+ { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name."},
{ LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeHelpText, "The help text to display for this command."},
- { LLDB_OPT_SET_1, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."},
+ { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, NULL, g_script_synchro_type, 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system."},
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
OpenPOWER on IntegriCloud