summaryrefslogtreecommitdiffstats
path: root/lldb/source/Commands
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Commands')
-rw-r--r--lldb/source/Commands/CommandObjectAdd.cpp51
-rw-r--r--lldb/source/Commands/CommandObjectAdd.h43
-rw-r--r--lldb/source/Commands/CommandObjectAlias.cpp225
-rw-r--r--lldb/source/Commands/CommandObjectAlias.h43
-rw-r--r--lldb/source/Commands/CommandObjectAppend.cpp95
-rw-r--r--lldb/source/Commands/CommandObjectAppend.h43
-rw-r--r--lldb/source/Commands/CommandObjectApropos.cpp96
-rw-r--r--lldb/source/Commands/CommandObjectApropos.h45
-rw-r--r--lldb/source/Commands/CommandObjectArgs.cpp279
-rw-r--r--lldb/source/Commands/CommandObjectArgs.h76
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp953
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.h235
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.cpp695
-rw-r--r--lldb/source/Commands/CommandObjectBreakpointCommand.h169
-rw-r--r--lldb/source/Commands/CommandObjectCall.cpp307
-rw-r--r--lldb/source/Commands/CommandObjectCall.h84
-rw-r--r--lldb/source/Commands/CommandObjectDelete.cpp32
-rw-r--r--lldb/source/Commands/CommandObjectDelete.h37
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.cpp431
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.h95
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp554
-rw-r--r--lldb/source/Commands/CommandObjectExpression.h105
-rw-r--r--lldb/source/Commands/CommandObjectFile.cpp170
-rw-r--r--lldb/source/Commands/CommandObjectFile.h79
-rw-r--r--lldb/source/Commands/CommandObjectFrame.cpp171
-rw-r--r--lldb/source/Commands/CommandObjectFrame.h40
-rw-r--r--lldb/source/Commands/CommandObjectHelp.cpp266
-rw-r--r--lldb/source/Commands/CommandObjectHelp.h59
-rw-r--r--lldb/source/Commands/CommandObjectImage.cpp1419
-rw-r--r--lldb/source/Commands/CommandObjectImage.h44
-rw-r--r--lldb/source/Commands/CommandObjectInfo.cpp32
-rw-r--r--lldb/source/Commands/CommandObjectInfo.h37
-rw-r--r--lldb/source/Commands/CommandObjectLog.cpp452
-rw-r--r--lldb/source/Commands/CommandObjectLog.h48
-rw-r--r--lldb/source/Commands/CommandObjectMemory.cpp680
-rw-r--r--lldb/source/Commands/CommandObjectMemory.h33
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp833
-rw-r--r--lldb/source/Commands/CommandObjectProcess.h37
-rw-r--r--lldb/source/Commands/CommandObjectQuit.cpp48
-rw-r--r--lldb/source/Commands/CommandObjectQuit.h51
-rw-r--r--lldb/source/Commands/CommandObjectRegister.cpp231
-rw-r--r--lldb/source/Commands/CommandObjectRegister.h44
-rw-r--r--lldb/source/Commands/CommandObjectRemove.cpp89
-rw-r--r--lldb/source/Commands/CommandObjectRemove.h44
-rw-r--r--lldb/source/Commands/CommandObjectScript.cpp149
-rw-r--r--lldb/source/Commands/CommandObjectScript.h58
-rw-r--r--lldb/source/Commands/CommandObjectSelect.cpp32
-rw-r--r--lldb/source/Commands/CommandObjectSelect.h37
-rw-r--r--lldb/source/Commands/CommandObjectSet.cpp153
-rw-r--r--lldb/source/Commands/CommandObjectSet.h44
-rw-r--r--lldb/source/Commands/CommandObjectSettings.cpp62
-rw-r--r--lldb/source/Commands/CommandObjectSettings.h44
-rw-r--r--lldb/source/Commands/CommandObjectShow.cpp74
-rw-r--r--lldb/source/Commands/CommandObjectShow.h44
-rw-r--r--lldb/source/Commands/CommandObjectSource.cpp127
-rw-r--r--lldb/source/Commands/CommandObjectSource.h48
-rw-r--r--lldb/source/Commands/CommandObjectSourceFile.cpp206
-rw-r--r--lldb/source/Commands/CommandObjectSourceFile.h80
-rw-r--r--lldb/source/Commands/CommandObjectStatus.cpp97
-rw-r--r--lldb/source/Commands/CommandObjectStatus.h44
-rw-r--r--lldb/source/Commands/CommandObjectSyntax.cpp148
-rw-r--r--lldb/source/Commands/CommandObjectSyntax.h51
-rw-r--r--lldb/source/Commands/CommandObjectTarget.cpp430
-rw-r--r--lldb/source/Commands/CommandObjectTarget.h41
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp1277
-rw-r--r--lldb/source/Commands/CommandObjectThread.h87
-rw-r--r--lldb/source/Commands/CommandObjectTranslate.cpp75
-rw-r--r--lldb/source/Commands/CommandObjectTranslate.h44
-rw-r--r--lldb/source/Commands/CommandObjectUnalias.cpp87
-rw-r--r--lldb/source/Commands/CommandObjectUnalias.h44
-rw-r--r--lldb/source/Commands/CommandObjectVariable.cpp801
-rw-r--r--lldb/source/Commands/CommandObjectVariable.h43
72 files changed, 14027 insertions, 0 deletions
diff --git a/lldb/source/Commands/CommandObjectAdd.cpp b/lldb/source/Commands/CommandObjectAdd.cpp
new file mode 100644
index 00000000000..cd1d02d22ff
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectAdd.cpp
@@ -0,0 +1,51 @@
+//===-- CommandObjectAdd.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectAdd.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectAdd
+//-------------------------------------------------------------------------
+
+CommandObjectAdd::CommandObjectAdd () :
+ CommandObject ("add",
+ "Allows the user to add a new command/function pair to the debugger's dictionary.",
+ "add <new-command-name> <script-function-name>")
+{
+}
+
+CommandObjectAdd::~CommandObjectAdd()
+{
+}
+
+
+bool
+CommandObjectAdd::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ result.AppendMessage ("This function has not been implemented yet.");
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return result.Succeeded();
+}
diff --git a/lldb/source/Commands/CommandObjectAdd.h b/lldb/source/Commands/CommandObjectAdd.h
new file mode 100644
index 00000000000..9aa59b61a7a
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectAdd.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectAdd.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectAdd_h_
+#define liblldb_CommandObjectAdd_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+//-------------------------------------------------------------------------
+// CommandObjectAdd
+//-------------------------------------------------------------------------
+
+class CommandObjectAdd : public CommandObject
+{
+public:
+
+ CommandObjectAdd ();
+
+ virtual
+ ~CommandObjectAdd ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectAdd_h_
diff --git a/lldb/source/Commands/CommandObjectAlias.cpp b/lldb/source/Commands/CommandObjectAlias.cpp
new file mode 100644
index 00000000000..50c2ab92e9f
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectAlias.cpp
@@ -0,0 +1,225 @@
+//===-- CommandObjectAlias.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectAlias.h"
+
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectAlias
+//-------------------------------------------------------------------------
+
+CommandObjectAlias::CommandObjectAlias () :
+ CommandObject ("alias",
+ "Allows users to define their own debugger command abbreviations.",
+ "alias <new_command> <old_command> [<options-for-aliased-command>]")
+{
+ 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 'alias sc script' // Creates the abbreviation 'sc' for the 'script' \n\
+ // command. \n\
+ '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\
+ 'alias bpi breakpoint list' // Creates the abbreviation 'bpi' 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\
+ '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. So 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). So 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 (dbg) alias bfl breakpoint set -f %1 -l %2 \n\
+ <... some time later ...> \n\
+ (dbg) 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 (dbg) alias pltty process launch -s -o %1 -e %1 \n\
+ (dbg) 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 alias bl3 breakpoint set -f %1 -l 3 // Always sets a breakpoint on line \n\
+ // 3 of whatever file is indicated. \n");
+
+}
+
+CommandObjectAlias::~CommandObjectAlias ()
+{
+}
+
+
+bool
+CommandObjectAlias::Execute (Args& args, CommandContext *context, CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ const int argc = args.GetArgumentCount();
+
+ if (argc < 2)
+ {
+ result.AppendError ("'alias' requires at least two arguments");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const std::string alias_command = args.GetArgumentAtIndex(0);
+ const std::string actual_command = args.GetArgumentAtIndex(1);
+
+ args.Shift(); // Shift the alias command word off the argument vector.
+ args.Shift(); // Shift the old command word off the argument vector.
+
+ // Verify that the command is alias'able, and get the appropriate command object.
+
+ if (interpreter->CommandExists (alias_command.c_str()))
+ {
+ result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be redefined.\n",
+ alias_command.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ CommandObjectSP command_obj_sp(interpreter->GetCommandSP (actual_command.c_str()));
+ CommandObjectSP subcommand_obj_sp;
+ bool use_subcommand = false;
+ if (command_obj_sp.get())
+ {
+ CommandObject *cmd_obj = command_obj_sp.get();
+ CommandObject *sub_cmd_obj;
+ OptionArgVectorSP option_arg_vector_sp = OptionArgVectorSP (new OptionArgVector);
+ OptionArgVector *option_arg_vector = option_arg_vector_sp.get();
+
+ if (cmd_obj->IsMultiwordObject())
+ {
+ if (argc >= 3)
+ {
+ const std::string sub_command = args.GetArgumentAtIndex(0);
+ assert (sub_command.length() != 0);
+ subcommand_obj_sp =
+ (((CommandObjectMultiword *) cmd_obj)->GetSubcommandSP (sub_command.c_str()));
+ if (subcommand_obj_sp.get())
+ {
+ sub_cmd_obj = subcommand_obj_sp.get();
+ use_subcommand = true;
+ args.Shift(); // Shift the sub_command word off the argument vector.
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Error occurred while attempting to look up command '%s %s'.\n",
+ alias_command.c_str(), sub_command.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+
+ // Verify & handle any options/arguments passed to the alias command
+
+ if (args.GetArgumentCount () > 0)
+ {
+ if ((!use_subcommand && (cmd_obj->WantsRawCommandString()))
+ || (use_subcommand && (sub_cmd_obj->WantsRawCommandString())))
+ {
+ result.AppendErrorWithFormat ("'%s' cannot be aliased with any options or arguments.\n",
+ (use_subcommand ? sub_cmd_obj->GetCommandName()
+ : cmd_obj->GetCommandName()));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ // options or arguments have been passed to the alias command, and must be verified & processed here.
+ if ((!use_subcommand && (cmd_obj->GetOptions() != NULL))
+ || (use_subcommand && (sub_cmd_obj->GetOptions() != NULL)))
+ {
+ Options *options;
+ if (use_subcommand)
+ options = sub_cmd_obj->GetOptions();
+ else
+ options = cmd_obj->GetOptions();
+ options->ResetOptionValues ();
+ args.Unshift ("dummy_arg");
+ args.ParseAliasOptions (*options, result, option_arg_vector);
+ args.Shift ();
+ if (result.Succeeded())
+ options->VerifyPartialOptions (result);
+ if (!result.Succeeded())
+ return false;
+ }
+ else
+ {
+ for (int i = 0; i < args.GetArgumentCount(); ++i)
+ option_arg_vector->push_back (OptionArgPair ("<argument>",
+ std::string (args.GetArgumentAtIndex (i))));
+ }
+ }
+
+ // Create the alias.
+
+ if (interpreter->AliasExists (alias_command.c_str())
+ || interpreter->UserCommandExists (alias_command.c_str()))
+ {
+ OptionArgVectorSP tmp_option_arg_sp (interpreter->GetAliasOptions (alias_command.c_str()));
+ if (tmp_option_arg_sp.get())
+ {
+ if (option_arg_vector->size() == 0)
+ interpreter->RemoveAliasOptions (alias_command.c_str());
+ }
+ result.AppendWarningWithFormat ("Overwriting existing definition for '%s'.\n", alias_command.c_str());
+ }
+
+ if (use_subcommand)
+ interpreter->AddAlias (alias_command.c_str(), subcommand_obj_sp);
+ else
+ interpreter->AddAlias (alias_command.c_str(), command_obj_sp);
+ if (option_arg_vector->size() > 0)
+ interpreter->AddOrReplaceAliasOptions (alias_command.c_str(), option_arg_vector_sp);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' is not an existing command.\n", actual_command.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+
+ return result.Succeeded();
+}
+
diff --git a/lldb/source/Commands/CommandObjectAlias.h b/lldb/source/Commands/CommandObjectAlias.h
new file mode 100644
index 00000000000..859b7cea049
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectAlias.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectAlias.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectAlias_h_
+#define liblldb_CommandObjectAlias_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectAlias
+//-------------------------------------------------------------------------
+
+class CommandObjectAlias : public CommandObject
+{
+public:
+
+ CommandObjectAlias ();
+
+ virtual
+ ~CommandObjectAlias ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectAlias_h_
diff --git a/lldb/source/Commands/CommandObjectAppend.cpp b/lldb/source/Commands/CommandObjectAppend.cpp
new file mode 100644
index 00000000000..613b85b4be9
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectAppend.cpp
@@ -0,0 +1,95 @@
+//===-- CommandObjectAppend.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectAppend.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-----------------------------------------------------------------------------
+// CommandObjectAppend
+//-----------------------------------------------------------------------------
+
+CommandObjectAppend::CommandObjectAppend () :
+ CommandObject ("append",
+ "Allows the user to append a value to a single debugger setting variable, for settings that are of list types. Type 'settings' to see a list of debugger setting variables",
+ "append <var-name> <value-string>")
+{
+}
+
+CommandObjectAppend::~CommandObjectAppend ()
+{
+}
+
+bool
+CommandObjectAppend::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ CommandInterpreter::VariableMap::iterator pos;
+
+ const int argc = command.GetArgumentCount();
+ if (argc < 2)
+ {
+ result.AppendError ("'append' requires at least two arguments");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const char *var_name = command.GetArgumentAtIndex(0);
+ command.Shift();
+
+
+ if (var_name == NULL || var_name[0] == '\0')
+ {
+ result.AppendError ("'set' command requires a valid variable name. No value supplied");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ StateVariable *var = interpreter->GetStateVariable(var_name);
+ if (var == NULL)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a settable internal variable.\n", var_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ if (var->GetType() == StateVariable::eTypeString)
+ {
+ for (int i = 0; i < command.GetArgumentCount(); ++i)
+ var->AppendStringValue (command.GetArgumentAtIndex(i));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else if (var->GetType() == StateVariable::eTypeStringArray)
+ {
+ var->GetArgs().AppendArguments (command);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Values cannot be appended to variable '%s'. Try 'set' instead.\n", var_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ return result.Succeeded();
+}
+
diff --git a/lldb/source/Commands/CommandObjectAppend.h b/lldb/source/Commands/CommandObjectAppend.h
new file mode 100644
index 00000000000..436283730fb
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectAppend.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectAppend.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectAppend_h_
+#define liblldb_CommandObjectAppend_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+//-----------------------------------------------------------------------------
+// CommandObjectAppend
+//-----------------------------------------------------------------------------
+
+class CommandObjectAppend : public CommandObject
+{
+public:
+ CommandObjectAppend ();
+
+ virtual
+ ~CommandObjectAppend ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectAppend_h_
diff --git a/lldb/source/Commands/CommandObjectApropos.cpp b/lldb/source/Commands/CommandObjectApropos.cpp
new file mode 100644
index 00000000000..0fcc093901f
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectApropos.cpp
@@ -0,0 +1,96 @@
+//===-- CommandObjectApropos.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectApropos.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectApropos
+//-------------------------------------------------------------------------
+
+CommandObjectApropos::CommandObjectApropos () :
+ CommandObject ("apropos",
+ "Finds a list of debugger commands related to a particular word/subject.",
+ "apropos <search-word>")
+{
+}
+
+CommandObjectApropos::~CommandObjectApropos()
+{
+}
+
+
+bool
+CommandObjectApropos::Execute (Args &command, CommandContext *context, CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ const int argc = command.GetArgumentCount ();
+
+ if (argc == 1)
+ {
+ const char *search_word = command.GetArgumentAtIndex(0);
+ if ((search_word != NULL)
+ && (strlen (search_word) > 0))
+ {
+ // The bulk of the work must be done inside the Command Interpreter, since the command dictionary
+ // is private.
+ StringList commands_found;
+ StringList commands_help;
+ interpreter->FindCommandsForApropos (search_word, commands_found, commands_help);
+ if (commands_found.GetSize() == 0)
+ {
+ result.AppendMessageWithFormat ("No commands found pertaining to '%s'.", search_word);
+ result.AppendMessage ("Try 'help' to see a complete list of debugger commands.");
+ }
+ else
+ {
+ result.AppendMessageWithFormat ("The following commands may relate to '%s':\n", search_word);
+ size_t max_len = 0;
+
+ for (int i = 0; i < commands_found.GetSize(); ++i)
+ {
+ int len = strlen (commands_found.GetStringAtIndex (i));
+ if (len > max_len)
+ max_len = len;
+ }
+
+ for (int i = 0; i < commands_found.GetSize(); ++i)
+ interpreter->OutputFormattedHelpText (result.GetOutputStream(), commands_found.GetStringAtIndex(i),
+ "--", commands_help.GetStringAtIndex(i), max_len);
+
+ }
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError ("'' is not a valid search word.\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("'apropos' must be called with exactly one argument.\n");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return result.Succeeded();
+}
diff --git a/lldb/source/Commands/CommandObjectApropos.h b/lldb/source/Commands/CommandObjectApropos.h
new file mode 100644
index 00000000000..a079a3fc4ac
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectApropos.h
@@ -0,0 +1,45 @@
+//===-- CommandObjectApropos.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectApropos_h_
+#define liblldb_CommandObjectApropos_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectApropos
+//-------------------------------------------------------------------------
+
+class CommandObjectApropos : public CommandObject
+{
+public:
+
+ CommandObjectApropos ();
+
+ virtual
+ ~CommandObjectApropos ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectApropos_h_
diff --git a/lldb/source/Commands/CommandObjectArgs.cpp b/lldb/source/Commands/CommandObjectArgs.cpp
new file mode 100644
index 00000000000..7f1fd3dda94
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectArgs.cpp
@@ -0,0 +1,279 @@
+//===-- CommandObjectArgs.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectArgs.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/StackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// This command is a toy. I'm just using it to have a way to construct the arguments to
+// calling functions.
+//
+
+CommandObjectArgs::CommandOptions::CommandOptions () :
+Options()
+{
+ // Keep only one place to reset the values to their defaults
+ ResetOptionValues();
+}
+
+
+CommandObjectArgs::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectArgs::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectArgs::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+}
+
+const lldb::OptionDefinition*
+CommandObjectArgs::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+CommandObjectArgs::CommandObjectArgs () :
+ CommandObject ("args",
+ "When stopped at the start of a function, reads function arguments of type (u?)int(8|16|32|64)_t, (void|char)*",
+ "args")
+{
+}
+
+CommandObjectArgs::~CommandObjectArgs ()
+{
+}
+
+Options *
+CommandObjectArgs::GetOptions ()
+{
+ return &m_options;
+}
+
+bool
+CommandObjectArgs::Execute(Args &command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ ConstString target_triple;
+
+ Process *process = context->GetExecutionContext().process;
+ if (!process)
+ {
+ result.AppendError ("Args found no process.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const ABI *abi = process->GetABI ();
+ if (!abi)
+ {
+ result.AppendError ("The current process has no ABI.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ int num_args = command.GetArgumentCount ();
+ int arg_index;
+
+ if (!num_args)
+ {
+ result.AppendError ("args requires at least one argument");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Thread *thread = context->GetExecutionContext ().thread;
+
+ if (!thread)
+ {
+ result.AppendError ("args found no thread.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ lldb::StackFrameSP thread_cur_frame = thread->GetCurrentFrame ();
+ if (!thread_cur_frame)
+ {
+ result.AppendError ("The current thread has no current frame.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Module *thread_module = thread_cur_frame->GetPC ().GetModule ();
+ if (!thread_module)
+ {
+ result.AppendError ("The PC has no associated module.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ TypeList *thread_type_list = thread_module->GetTypeList ();
+ if (!thread_type_list)
+ {
+ result.AppendError ("The module has no type list.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ ClangASTContext &ast_context = thread_type_list->GetClangASTContext();
+
+ ValueList value_list;
+
+ for (arg_index = 0; arg_index < num_args; ++arg_index)
+ {
+ const char *arg_type_cstr = command.GetArgumentAtIndex(arg_index);
+ Value value;
+ value.SetValueType(Value::eValueTypeScalar);
+ void *type;
+
+ char *int_pos;
+ if ((int_pos = strstr (arg_type_cstr, "int")))
+ {
+ Encoding encoding = eEncodingSint;
+
+ int width = 0;
+
+ if (int_pos > arg_type_cstr + 1)
+ {
+ result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ if (int_pos == arg_type_cstr + 1 && arg_type_cstr[0] != 'u')
+ {
+ result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ if (arg_type_cstr[0] == 'u')
+ {
+ encoding = eEncodingUint;
+ }
+
+ char *width_pos = int_pos + 3;
+
+ if (!strcmp (width_pos, "8_t"))
+ width = 8;
+ else if (!strcmp (width_pos, "16_t"))
+ width = 16;
+ else if (!strcmp (width_pos, "32_t"))
+ width = 32;
+ else if (!strcmp (width_pos, "64_t"))
+ width = 64;
+ else
+ {
+ result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ type = ast_context.GetBuiltinTypeForEncodingAndBitSize(encoding, width);
+
+ if (!type)
+ {
+ result.AppendErrorWithFormat ("Couldn't get Clang type for format %s (%s integer, width %d).\n",
+ arg_type_cstr,
+ (encoding == eEncodingSint ? "signed" : "unsigned"),
+ width);
+
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else if (strchr (arg_type_cstr, '*'))
+ {
+ if (!strcmp (arg_type_cstr, "void*"))
+ type = ast_context.CreatePointerType (ast_context.GetVoidBuiltInType ());
+ else if (!strcmp (arg_type_cstr, "char*"))
+ type = ast_context.GetCStringType (false);
+ else
+ {
+ result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Invalid format: %s.\n", arg_type_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ value.SetContext (Value::eContextTypeOpaqueClangQualType, type);
+
+ value_list.PushValue(value);
+ }
+
+ if (!abi->GetArgumentValues (*thread, value_list))
+ {
+ result.AppendError ("Couldn't get argument values");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ result.GetOutputStream ().Printf("Arguments : \n");
+
+ for (arg_index = 0; arg_index < num_args; ++arg_index)
+ {
+ result.GetOutputStream ().Printf ("%d (%s): ", arg_index, command.GetArgumentAtIndex (arg_index));
+ value_list.GetValueAtIndex (arg_index)->Dump (&result.GetOutputStream ());
+ result.GetOutputStream ().Printf("\n");
+ }
+
+ return result.Succeeded();
+}
+
+lldb::OptionDefinition
+CommandObjectArgs::CommandOptions::g_option_table[] =
+{
+ { 0, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."},
+ { 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
diff --git a/lldb/source/Commands/CommandObjectArgs.h b/lldb/source/Commands/CommandObjectArgs.h
new file mode 100644
index 00000000000..d326d423247
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectArgs.h
@@ -0,0 +1,76 @@
+//===-- CommandObjectArgs.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectArgs_h_
+#define liblldb_CommandObjectArgs_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/Language.h"
+
+namespace lldb_private {
+
+ class CommandObjectArgs : public CommandObject
+ {
+ public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+ };
+
+ CommandObjectArgs ();
+
+ virtual
+ ~CommandObjectArgs ();
+
+ virtual
+ Options *
+ GetOptions ();
+
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual bool
+ WantsRawCommandString() { return false; }
+
+ protected:
+
+ CommandOptions m_options;
+ };
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectArgs_h_
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
new file mode 100644
index 00000000000..d24ba8f553b
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -0,0 +1,953 @@
+//===-- CommandObjectBreakpoint.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectBreakpoint.h"
+#include "CommandObjectBreakpointCommand.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/Breakpoint.h"
+#include "lldb/Breakpoint/BreakpointIDList.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Target/StackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static void
+AddBreakpointDescription (CommandContext *context, StreamString *s, Breakpoint *bp, lldb::DescriptionLevel level)
+{
+ s->IndentMore();
+ bp->GetDescription (s, level, true);
+ s->IndentLess();
+ s->EOL();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointSet::CommandOptions
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointSet::CommandOptions::CommandOptions() :
+ Options (),
+ m_filename (),
+ m_line_num (0),
+ m_column (0),
+ m_ignore_inlines (false),
+ m_func_name (),
+ m_func_regexp (),
+ m_modules (),
+ m_load_addr()
+{
+ BuildValidOptionSets();
+}
+
+CommandObjectBreakpointSet::CommandOptions::~CommandOptions ()
+{
+}
+
+lldb::OptionDefinition
+CommandObjectBreakpointSet::CommandOptions::g_option_table[] =
+{
+ { 0, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<filename>",
+ "Set the breakpoint by source location in this particular file."},
+
+ { 0, true, "line", 'l', required_argument, NULL, 0, "<linenum>",
+ "Set the breakpoint by source location at this particular line."},
+
+ { 0, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>",
+ "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."},
+
+ // Comment out this option for the moment, as we don't actually use it, but will in the future.
+ // This way users won't see it, but the infrastructure is left in place.
+ // { 0, false, "column", 'c', required_argument, NULL, "<column>",
+ // "Set the breakpoint by source location at this particular column."},
+
+ { 0, false, "ignore_inlines", 'i', no_argument, NULL, 0, NULL,
+ "Ignore inlined subroutines when setting the breakppoint." },
+
+ { 1, true, "address", 'a', required_argument, NULL, 0, "<address>",
+ "Set the breakpoint by address, at the specified address."},
+
+ { 1, false, "ignore_inlines", 'i', no_argument, NULL, 0, NULL,
+ "Ignore inlined subroutines when setting the breakppoint." },
+
+ { 2, true, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, "<function-name>",
+ "Set the breakpoint by function name." },
+
+ { 2, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>",
+ "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."},
+
+ { 2, false, "ignore_inlines", 'i', no_argument, NULL, 0, NULL,
+ "Ignore inlined subroutines when setting the breakpoint." },
+
+ { 3, true, "func_regex", 'r', required_argument, NULL, 0, "<regular-expression>",
+ "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." },
+
+ { 3, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, "<shlib-name>",
+ "Set the breakpoint only in this shared library (can use this option multiple times for multiple shlibs)."},
+
+ { 3, false, "ignore_inlines", 'i', no_argument, NULL, 0, NULL,
+ "Ignore inlined subroutines when setting the breakpoint." },
+
+ { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+const lldb::OptionDefinition*
+CommandObjectBreakpointSet::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+Error
+CommandObjectBreakpointSet::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'a':
+ m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
+ if (m_load_addr == LLDB_INVALID_ADDRESS)
+ m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
+
+ if (m_load_addr == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", optarg);
+ break;
+
+ case 'c':
+ m_column = Args::StringToUInt32 (option_arg, 0);
+ break;
+ case 'f':
+ m_filename = option_arg;
+ break;
+ case 'i':
+ m_ignore_inlines = true;
+ break;
+ case 'l':
+ m_line_num = Args::StringToUInt32 (option_arg, 0);
+ break;
+ case 'n':
+ m_func_name = option_arg;
+ break;
+ case 'r':
+ m_func_regexp = option_arg;
+ break;
+ case 's':
+ {
+ m_modules.push_back (std::string (option_arg));
+ break;
+ }
+ default:
+ error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectBreakpointSet::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+
+ m_filename.clear();
+ m_line_num = 0;
+ m_column = 0;
+ m_ignore_inlines = false;
+ m_func_name.clear();
+ m_func_regexp.clear();
+ m_load_addr = LLDB_INVALID_ADDRESS;
+ m_modules.clear();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointSet
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointSet::CommandObjectBreakpointSet () :
+ CommandObject ("breakpoint set", "Sets a breakpoint or set of breakpoints in the executable.",
+ "breakpoint set <cmd-options>")
+{
+}
+
+CommandObjectBreakpointSet::~CommandObjectBreakpointSet ()
+{
+}
+
+Options *
+CommandObjectBreakpointSet::GetOptions ()
+{
+ return &m_options;
+}
+
+bool
+CommandObjectBreakpointSet::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("Invalid target, set executable file using 'file' command.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ // The following are the various types of breakpoints that could be set:
+ // 1). -f -l -p [-s -g] (setting breakpoint by source location)
+ // 2). -a [-s -g] (setting breakpoint by address)
+ // 3). -n [-s -g] (setting breakpoint by function name)
+ // 4). -r [-s -g] (setting breakpoint by function name regular expression)
+
+ BreakpointSetType break_type = eSetTypeInvalid;
+
+ if (m_options.m_line_num != 0)
+ break_type = eSetTypeFileAndLine;
+ else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS)
+ break_type = eSetTypeAddress;
+ else if (!m_options.m_func_name.empty())
+ break_type = eSetTypeFunctionName;
+ else if (!m_options.m_func_regexp.empty())
+ break_type = eSetTypeFunctionRegexp;
+
+ ModuleSP module_sp = target->GetExecutableModule();
+ Breakpoint *bp = NULL;
+ FileSpec module;
+ bool use_module = false;
+ int num_modules = m_options.m_modules.size();
+
+ if ((num_modules > 0) && (break_type != eSetTypeAddress))
+ use_module = true;
+
+ switch (break_type)
+ {
+ case eSetTypeFileAndLine: // Breakpoint by source position
+ {
+ FileSpec file;
+ if (m_options.m_filename.empty())
+ {
+ StackFrame *cur_frame = context->GetExecutionContext().frame;
+ if (cur_frame == NULL)
+ {
+ result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame.");
+ result.SetStatus (eReturnStatusFailed);
+ break;
+ }
+ else if (!cur_frame->HasDebugInformation())
+ {
+ result.AppendError ("Attempting to set breakpoint by line number alone but selected frame has no debug info.");
+ result.SetStatus (eReturnStatusFailed);
+ break;
+ }
+ else
+ {
+ const SymbolContext &context = cur_frame->GetSymbolContext(true);
+ if (context.line_entry.file)
+ {
+ file = context.line_entry.file;
+ }
+ else if (context.comp_unit != NULL)
+ { file = context.comp_unit;
+ }
+ else
+ {
+ result.AppendError ("Attempting to set breakpoint by line number alone but can't find the file for the selected frame.");
+ result.SetStatus (eReturnStatusFailed);
+ break;
+ }
+ }
+ }
+ else
+ {
+ file.SetFile(m_options.m_filename.c_str());
+ }
+
+ if (use_module)
+ {
+ for (int i = 0; i < num_modules; ++i)
+ {
+ module.SetFile(m_options.m_modules[i].c_str());
+ bp = target->CreateBreakpoint (&module,
+ file,
+ m_options.m_line_num,
+ m_options.m_ignore_inlines).get();
+ if (bp)
+ {
+ StreamString &output_stream = result.GetOutputStream();
+ output_stream.Printf ("Breakpoint created: ");
+ bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
+ output_stream.EOL();
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
+ m_options.m_modules[i].c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ bp = target->CreateBreakpoint (NULL,
+ file,
+ m_options.m_line_num,
+ m_options.m_ignore_inlines).get();
+ }
+ break;
+ case eSetTypeAddress: // Breakpoint by address
+ bp = target->CreateBreakpoint (m_options.m_load_addr, false).get();
+ break;
+ case eSetTypeFunctionName: // Breakpoint by function name
+ if (use_module)
+ {
+ for (int i = 0; i < num_modules; ++i)
+ {
+ module.SetFile(m_options.m_modules[i].c_str());
+ bp = target->CreateBreakpoint (&module, m_options.m_func_name.c_str()).get();
+ if (bp)
+ {
+ StreamString &output_stream = result.GetOutputStream();
+ output_stream.Printf ("Breakpoint created: ");
+ bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
+ output_stream.EOL();
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
+ m_options.m_modules[i].c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ bp = target->CreateBreakpoint (NULL, m_options.m_func_name.c_str()).get();
+ break;
+ case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name
+ {
+ RegularExpression regexp(m_options.m_func_regexp.c_str());
+ if (use_module)
+ {
+ for (int i = 0; i < num_modules; ++i)
+ {
+ module.SetFile(m_options.m_modules[i].c_str());
+ bp = target->CreateBreakpoint (&module, regexp).get();
+ if (bp)
+ {
+ StreamString &output_stream = result.GetOutputStream();
+ output_stream.Printf ("Breakpoint created: ");
+ bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
+ output_stream.EOL();
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n",
+ m_options.m_modules[i].c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ bp = target->CreateBreakpoint (NULL, regexp).get();
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (bp && !use_module)
+ {
+ StreamString &output_stream = result.GetOutputStream();
+ output_stream.Printf ("Breakpoint created: ");
+ bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief);
+ output_stream.EOL();
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else if (!bp)
+ {
+ result.AppendError ("Breakpoint creation failed: No breakpoint created.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return result.Succeeded();
+}
+
+
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpoint
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint (CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("breakpoint",
+ "A set of commands for operating on breakpoints.",
+ "breakpoint <command> [<command-options>]")
+{
+ bool status;
+
+ CommandObjectSP list_command_object (new CommandObjectBreakpointList ());
+ CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete ());
+ CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable ());
+ CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable ());
+ CommandObjectSP set_command_object (new CommandObjectBreakpointSet ());
+ CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter));
+
+ enable_command_object->SetCommandName("breakpoint enable");
+ disable_command_object->SetCommandName("breakpoint disable");
+ set_command_object->SetCommandName("breakpoint set");
+ command_command_object->SetCommandName ("breakpoint command");
+ list_command_object->SetCommandName ("breakpoint list");
+
+ status = LoadSubCommand (list_command_object, "list", interpreter);
+ status = LoadSubCommand (enable_command_object, "enable", interpreter);
+ status = LoadSubCommand (disable_command_object, "disable", interpreter);
+ status = LoadSubCommand (delete_command_object, "delete", interpreter);
+ status = LoadSubCommand (set_command_object, "set", interpreter);
+ status = LoadSubCommand (command_command_object, "command", interpreter);
+}
+
+CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint ()
+{
+}
+
+void
+CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result,
+ BreakpointIDList *valid_ids)
+{
+ // args can be strings representing 1). integers (for breakpoint ids)
+ // 2). the full breakpoint & location canonical representation
+ // 3). the word "to" or a hyphen, representing a range (in which case there
+ // had *better* be an entry both before & after of one of the first two types.
+
+ Args temp_args;
+
+ // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to
+ // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead generate a list of strings for
+ // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS.
+
+ BreakpointIDList::FindAndReplaceIDRanges (args, target, result, temp_args);
+
+ // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList:
+
+ valid_ids->InsertStringArray ((const char **) temp_args.GetArgumentVector(), temp_args.GetArgumentCount(), result);
+
+ // At this point, all of the breakpoint ids that the user passed in have been converted to breakpoint IDs
+ // and put into valid_ids.
+
+ if (result.Succeeded())
+ {
+ // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list
+ // of breakpoint id's and verify that they correspond to valid/currently set breakpoints.
+
+ for (int i = 0; i < valid_ids->Size(); ++i)
+ {
+ BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i);
+ Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+ if (breakpoint != NULL)
+ {
+ int num_locations = breakpoint->GetNumLocations();
+ if (cur_bp_id.GetLocationID() > num_locations)
+ {
+ StreamString id_str;
+ BreakpointID::GetCanonicalReference (&id_str, cur_bp_id.GetBreakpointID(),
+ cur_bp_id.GetLocationID());
+ i = valid_ids->Size() + 1;
+ result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n",
+ id_str.GetData());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ i = valid_ids->Size() + 1;
+ result.AppendErrorWithFormat ("'%d' is not a currently valid breakpoint id.\n", cur_bp_id.GetBreakpointID());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointList::Options
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointList::CommandOptions::CommandOptions() :
+ Options (),
+ m_level (lldb::eDescriptionLevelFull) // Breakpoint List defaults to brief descriptions
+{
+ BuildValidOptionSets();
+}
+
+CommandObjectBreakpointList::CommandOptions::~CommandOptions ()
+{
+}
+
+lldb::OptionDefinition
+CommandObjectBreakpointList::CommandOptions::g_option_table[] =
+{
+ { 0, false, "brief", 'b', no_argument, NULL, 0, NULL,
+ "Give a brief description of the breakpoint (no location info)."},
+
+ // FIXME: We need to add an "internal" command, and then add this sort of thing to it.
+ // But I need to see it for now, and don't want to wait.
+ { 0, false, "internal", 'i', no_argument, NULL, 0, NULL,
+ "Show debugger internal breakpoints" },
+
+ { 1, false, "full", 'f', no_argument, NULL, 0, NULL,
+ "Give a full description of the breakpoint and its locations."},
+ // DITTO FIXME
+ { 1, false, "internal", 'i', no_argument, NULL, 0, NULL,
+ "Show debugger internal breakpoints" },
+
+ { 2, false, "verbose", 'v', no_argument, NULL, 0, NULL,
+ "Explain everything we know about the breakpoint (for debugging debugger bugs)." },
+ // DITTO FIXME
+ { 2, false, "internal", 'i', no_argument, NULL, 0, NULL,
+ "Show debugger internal breakpoints" },
+
+ { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+const lldb::OptionDefinition*
+CommandObjectBreakpointList::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+Error
+CommandObjectBreakpointList::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'b':
+ m_level = lldb::eDescriptionLevelBrief;
+ break;
+ case 'f':
+ m_level = lldb::eDescriptionLevelFull;
+ break;
+ case 'v':
+ m_level = lldb::eDescriptionLevelVerbose;
+ break;
+ case 'i':
+ m_internal = true;
+ break;
+ default:
+ error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectBreakpointList::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+
+ m_level = lldb::eDescriptionLevelFull;
+ m_internal = false;
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointList
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointList::CommandObjectBreakpointList () :
+ CommandObject ("breakpoint list",
+ "List some or all breakpoints at configurable levels of detail.",
+ "breakpoint list [<breakpoint-id>]")
+{
+}
+
+CommandObjectBreakpointList::~CommandObjectBreakpointList ()
+{
+}
+
+Options *
+CommandObjectBreakpointList::GetOptions ()
+{
+ return &m_options;
+}
+
+bool
+CommandObjectBreakpointList::Execute
+(
+ Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("Invalid target, set executable file using 'file' command.");
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+ const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal);
+ size_t num_breakpoints = breakpoints.GetSize();
+
+ if (num_breakpoints == 0)
+ {
+ result.AppendMessage ("No breakpoints currently set.");
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+ StreamString &output_stream = result.GetOutputStream();
+
+ if (args.GetArgumentCount() == 0)
+ {
+ // No breakpoint selected; show info about all currently set breakpoints.
+ result.AppendMessage ("Current breakpoints:");
+ for (int i = 0; i < num_breakpoints; ++i)
+ {
+ Breakpoint *breakpoint = breakpoints.GetBreakpointByIndex (i).get();
+ AddBreakpointDescription (context, &output_stream, breakpoint, m_options.m_level);
+ }
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ // Particular breakpoints selected; show info about that breakpoint.
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ for (int i = 0; i < valid_bp_ids.Size(); ++i)
+ {
+ BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+ Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+ AddBreakpointDescription (context, &output_stream, breakpoint, m_options.m_level);
+ }
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError ("Invalid breakpoint id.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+
+ return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointEnable
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointEnable::CommandObjectBreakpointEnable () :
+ CommandObject ("enable",
+ "Enables the specified disabled breakpoint(s). If no breakpoints are specified, enables all of them.",
+ "breakpoint enable [<breakpoint-id> | <breakpoint-id-list>]")
+{
+ // This command object can either be called via 'enable' or 'breakpoint enable'. Because it has two different
+ // potential invocation methods, we need to be a little tricky about generating the syntax string.
+ //StreamString tmp_string;
+ //tmp_string.Printf ("%s <breakpoint-id>", GetCommandName());
+ //m_cmd_syntax.assign (tmp_string.GetData(), tmp_string.GetSize());
+}
+
+
+CommandObjectBreakpointEnable::~CommandObjectBreakpointEnable ()
+{
+}
+
+
+bool
+CommandObjectBreakpointEnable::Execute (Args& args, CommandContext *context,
+ CommandInterpreter *interpreter, CommandReturnObject &result)
+{
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("Invalid target, set executable file using 'file' command.");
+ 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 be enabled.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (args.GetArgumentCount() == 0)
+ {
+ // No breakpoint selected; enable all currently set breakpoints.
+ target->EnableAllBreakpoints ();
+ result.AppendMessageWithFormat ("All breakpoints enabled. (%d breakpoints)\n", num_breakpoints);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ // Particular breakpoint selected; enable that breakpoint.
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ int enable_count = 0;
+ int loc_count = 0;
+ for (int i = 0; i < valid_bp_ids.Size(); ++i)
+ {
+ BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+
+ if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+ {
+ Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+ if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+ {
+ BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
+ if (location)
+ {
+ location->SetEnabled (true);
+ breakpoint->SetEnabled (true);
+ ++loc_count;
+ }
+ }
+ else
+ {
+ target->EnableBreakpointByID (cur_bp_id.GetBreakpointID());
+ ++enable_count;
+
+ int num_locations = breakpoint->GetNumLocations ();
+ for (int j = 0; j < num_locations; ++j)
+ {
+ BreakpointLocation *cur_loc = breakpoint->GetLocationAtIndex(j).get();
+ if (cur_loc)
+ cur_loc->SetEnabled (true);
+ }
+ }
+ }
+ }
+ result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+
+ return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointDisable
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointDisable::CommandObjectBreakpointDisable () :
+ CommandObject ("disable",
+ "Disables the specified breakpoint(s) without removing it/them. If no breakpoints are specified, disables them all.",
+ "disable [<breakpoint-id> | <breakpoint-id-list>]")
+{
+ // This command object can either be called via 'enable' or 'breakpoint enable'. Because it has two different
+ // potential invocation methods, we need to be a little tricky about generating the syntax string.
+ //StreamString tmp_string;
+ //tmp_string.Printf ("%s <breakpoint-id>", GetCommandName());
+ //m_cmd_syntax.assign(tmp_string.GetData(), tmp_string.GetSize());
+}
+
+CommandObjectBreakpointDisable::~CommandObjectBreakpointDisable ()
+{
+}
+
+bool
+CommandObjectBreakpointDisable::Execute (Args& args, CommandContext *context,
+ CommandInterpreter *interpreter, CommandReturnObject &result)
+{
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("Invalid target, set executable file using 'file' command.");
+ 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 be disabled.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (args.GetArgumentCount() == 0)
+ {
+ // No breakpoint selected; disable all currently set breakpoints.
+ target->DisableAllBreakpoints ();
+ result.AppendMessageWithFormat ("All breakpoints disabled. (%d breakpoints)\n", num_breakpoints);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ // Particular breakpoint selected; disable that breakpoint.
+ BreakpointIDList valid_bp_ids;
+
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ int disable_count = 0;
+ int loc_count = 0;
+ for (int i = 0; i < valid_bp_ids.Size(); ++i)
+ {
+ BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+
+ if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+ {
+ Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+ if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+ {
+ BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
+ if (location)
+ {
+ location->SetEnabled (false);
+ ++loc_count;
+ }
+ }
+ else
+ {
+ target->DisableBreakpointByID (cur_bp_id.GetBreakpointID());
+ ++disable_count;
+
+ int num_locations = breakpoint->GetNumLocations();
+ for (int j = 0; j < num_locations; ++j)
+ {
+ BreakpointLocation *cur_loc = breakpoint->GetLocationAtIndex(j).get();
+ if (cur_loc)
+ cur_loc->SetEnabled (false);
+ }
+ }
+ }
+ }
+ result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+
+ return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointDelete
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointDelete::CommandObjectBreakpointDelete() :
+ CommandObject ("breakpoint delete",
+ "Delete the specified breakpoint(s). If no breakpoints are specified, deletes them all.",
+ "breakpoint delete [<breakpoint-id> | <breakpoint-id-list>]")
+{
+}
+
+
+CommandObjectBreakpointDelete::~CommandObjectBreakpointDelete ()
+{
+}
+
+bool
+CommandObjectBreakpointDelete::Execute (Args& args, CommandContext *context,
+ CommandInterpreter *interpreter, CommandReturnObject &result)
+{
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("Invalid target, set executable file using 'file' command.");
+ 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 be deleted.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (args.GetArgumentCount() == 0)
+ {
+ // No breakpoint selected; disable all currently set breakpoints.
+ if (args.GetArgumentCount() != 0)
+ {
+ result.AppendErrorWithFormat ("Specify breakpoints to delete with the -i option.\n");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ target->RemoveAllBreakpoints ();
+ result.AppendMessageWithFormat ("All breakpoints removed. (%d breakpoints)\n", num_breakpoints);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ // Particular breakpoint selected; disable that breakpoint.
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (args, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ int delete_count = 0;
+ int disable_count = 0;
+ for (int i = 0; i < valid_bp_ids.Size(); ++i)
+ {
+ BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i);
+
+ if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID)
+ {
+ if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID)
+ {
+ Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get();
+ BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get();
+ // It makes no sense to try to delete individual locations, so we disable them instead.
+ if (location)
+ {
+ location->SetEnabled (false);
+ ++disable_count;
+ }
+ }
+ else
+ {
+ target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID());
+ ++delete_count;
+ }
+ }
+ }
+ result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n",
+ delete_count, disable_count);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ return result.Succeeded();
+}
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h
new file mode 100644
index 00000000000..49007438b28
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectBreakpoint.h
@@ -0,0 +1,235 @@
+//===-- CommandObjectBreakpoint.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectBreakpoint_h_
+#define liblldb_CommandObjectBreakpoint_h_
+
+// C Includes
+// C++ Includes
+
+#include <utility>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Address.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/STLUtils.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpoint
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordBreakpoint : public CommandObjectMultiword
+{
+public:
+ CommandObjectMultiwordBreakpoint (CommandInterpreter *interpreter);
+
+ virtual
+ ~CommandObjectMultiwordBreakpoint ();
+
+ static void
+ VerifyBreakpointIDs (Args &args, Target *target, CommandReturnObject &result, BreakpointIDList *valid_ids);
+
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpointSet
+//-------------------------------------------------------------------------
+
+
+class CommandObjectBreakpointSet : public CommandObject
+{
+public:
+
+ typedef enum BreakpointSetType
+ {
+ eSetTypeInvalid,
+ eSetTypeFileAndLine,
+ eSetTypeAddress,
+ eSetTypeFunctionName,
+ eSetTypeFunctionRegexp,
+ } BreakpointSetType;
+
+ CommandObjectBreakpointSet ();
+
+ virtual
+ ~CommandObjectBreakpointSet ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual Options *
+ GetOptions ();
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ std::string m_filename;
+ unsigned int m_line_num;
+ unsigned int m_column;
+ bool m_ignore_inlines;
+ std::string m_func_name;
+ std::string m_func_regexp;
+ lldb::addr_t m_load_addr;
+ STLStringArray m_modules;
+
+ };
+
+private:
+ CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointEnable
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointEnable : public CommandObject
+{
+public:
+ CommandObjectBreakpointEnable ();
+
+ virtual
+ ~CommandObjectBreakpointEnable ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+private:
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointDisable
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointDisable : public CommandObject
+{
+public:
+ CommandObjectBreakpointDisable ();
+
+ virtual
+ ~CommandObjectBreakpointDisable ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+private:
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointList
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointList : public CommandObject
+{
+public:
+ CommandObjectBreakpointList ();
+
+ virtual
+ ~CommandObjectBreakpointList ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual Options *
+ GetOptions ();
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition *
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ lldb::DescriptionLevel m_level;
+
+ bool m_internal;
+ };
+
+private:
+ CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointDelete : public CommandObject
+{
+public:
+ CommandObjectBreakpointDelete ();
+
+ virtual
+ ~CommandObjectBreakpointDelete ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+private:
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectBreakpoint_h_
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
new file mode 100644
index 00000000000..8a5a443ea8e
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp
@@ -0,0 +1,695 @@
+//===-- CommandObjectBreakpointCommand.cpp ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+
+
+#include "CommandObjectBreakpointCommand.h"
+#include "CommandObjectBreakpoint.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::CommandOptions
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointCommandAdd::CommandOptions::CommandOptions () :
+ Options ()
+{
+ BuildValidOptionSets();
+}
+
+CommandObjectBreakpointCommandAdd::CommandOptions::~CommandOptions ()
+{
+}
+
+lldb::OptionDefinition
+CommandObjectBreakpointCommandAdd::CommandOptions::g_option_table[] =
+{
+ { 0, true, "script", 's', no_argument, NULL, 0, NULL,
+ "Write the breakpoint command script in the default scripting language."},
+
+ { 1, true, "python", 'p', no_argument, NULL, 0, NULL,
+ "Write the breakpoint command script in the Python scripting language."},
+
+ { 2, true, "commands", 'c', no_argument, NULL, 0, NULL,
+ "Write the breakpoint command script using the command line commands."},
+
+ { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+const lldb::OptionDefinition*
+CommandObjectBreakpointCommandAdd::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+
+Error
+CommandObjectBreakpointCommandAdd::CommandOptions::SetOptionValue
+(
+ int option_idx,
+ const char *option_arg
+)
+{
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 's':
+ m_use_commands = false;
+ m_use_script_language = true;
+ m_script_language = eScriptLanguageDefault;
+ break;
+ case 'p':
+ m_use_commands = false;
+ m_use_script_language = true;
+ m_script_language = eScriptLanguagePython;
+ break;
+ case 'c':
+ m_use_commands = true;
+ m_use_script_language = false;
+ m_script_language = eScriptLanguageNone;
+ break;
+ default:
+ break;
+ }
+ return error;
+}
+
+void
+CommandObjectBreakpointCommandAdd::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+
+ m_use_commands = false;
+ m_use_script_language = false;
+ m_script_language = eScriptLanguageNone;
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandAdd
+//-------------------------------------------------------------------------
+
+
+CommandObjectBreakpointCommandAdd::CommandObjectBreakpointCommandAdd () :
+ CommandObject ("add",
+ "Adds a set of commands to a breakpoint to be executed whenever a breakpoint is hit.",
+ "breakpoint command add <cmd-options> <breakpoint-id>")
+{
+ SetHelpLong (
+"\nGeneral information about entering breakpoint commands \n\
+------------------------------------------------------ \n\
+ \n\
+This command will cause you to be prompted to enter the command or set \n\
+of commands you wish to be executed when the specified breakpoint is \n\
+hit. You will be told to enter your command(s), and will see a '> ' \n\
+prompt. Because you can enter one or many commands to be executed when \n\
+a breakpoint is hit, you will continue to be prompted after each \n\
+new-line that you enter, until you enter the word 'DONE', which will \n\
+cause the commands you have entered to be stored with the breakpoint \n\
+and executed when the breakpoint is hit. \n\
+ \n\
+Syntax checking is not necessarily done when breakpoint commands are \n\
+entered. An improperly written breakpoint command will attempt to get \n\
+executed when the breakpoint gets hit, and usually silently fail. If \n\
+your breakpoint command does not appear to be getting executed, go \n\
+back and check your syntax. \n\
+ \n\
+ \n\
+Special information about PYTHON breakpoint commands \n\
+---------------------------------------------------- \n\
+ \n\
+You may enter either one line of Python or multiple lines of Python \n\
+(including defining whole functions, if desired). If you enter a \n\
+single line of Python, that will be passed to the Python interpreter \n\
+'as is' when the breakpoint gets hit. If you enter function \n\
+definitions, they will be passed to the Python interpreter as soon as \n\
+you finish entering the breakpoint command, and they can be called \n\
+later (don't forget to add calls to them, if you want them called when \n\
+the breakpoint is hit). If you enter multiple lines of Python that \n\
+are not function definitions, they will be collected into a new, \n\
+automatically generated Python function, and a call to the newly \n\
+generated function will be attached to the breakpoint. Important \n\
+Note: Because loose Python code gets collected into functions, if you \n\
+want to access global variables in the 'loose' code, you need to \n\
+specify that they are global, using the 'global' keyword. Be sure to \n\
+use correct Python syntax, including indentation, when entering Python \n\
+breakpoint commands. \n\
+ \n\
+Example Python one-line breakpoint command: \n\
+ \n\
+(lldb) breakpoint command add -p 1 \n\
+Enter your Python command(s). Type 'DONE' to end. \n\
+> print \"Hit this breakpoint!\" \n\
+> DONE \n\
+ \n\
+Example multiple line Python breakpoint command, using function definition: \n\
+ \n\
+(lldb) breakpoint command add -p 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 -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\
+Special information debugger command breakpoint commands \n\
+--------------------------------------------------------- \n\
+ \n\
+You may enter any debugger command, exactly as you would at the \n\
+debugger prompt. You may enter as many debugger commands as you like, \n\
+but do NOT enter more than one command per line. \n" );
+}
+
+CommandObjectBreakpointCommandAdd::~CommandObjectBreakpointCommandAdd ()
+{
+}
+
+bool
+CommandObjectBreakpointCommandAdd::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ Target *target = context->GetTarget();
+
+ 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 (command.GetArgumentCount() == 0)
+ {
+ result.AppendError ("No breakpoint specified to which to add the commands");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ for (int i = 0; i < valid_bp_ids.Size(); ++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)
+ {
+ if (m_options.m_use_script_language)
+ {
+ interpreter->GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp_loc_sp->GetLocationOptions(),
+ result);
+ }
+ else
+ {
+ CollectDataForBreakpointCommandCallback (bp_loc_sp->GetLocationOptions(), result);
+ }
+ }
+ }
+ else
+ {
+ if (m_options.m_use_script_language)
+ {
+ interpreter->GetScriptInterpreter()->CollectDataForBreakpointCommandCallback (bp->GetOptions(),
+ result);
+ }
+ else
+ {
+ CollectDataForBreakpointCommandCallback (bp->GetOptions(), result);
+ }
+ }
+ }
+ }
+ }
+
+ return result.Succeeded();
+}
+
+Options *
+CommandObjectBreakpointCommandAdd::GetOptions ()
+{
+ return &m_options;
+}
+
+const char *g_reader_instructions = "Enter your debugger command(s). Type 'DONE' to end.";
+
+void
+CommandObjectBreakpointCommandAdd::CollectDataForBreakpointCommandCallback
+(
+ BreakpointOptions *bp_options,
+ CommandReturnObject &result
+)
+{
+ InputReaderSP reader_sp (new InputReader());
+ std::auto_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
+ if (reader_sp && data_ap.get())
+ {
+ BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
+ bp_options->SetCallback (CommandObjectBreakpointCommand::BreakpointOptionsCallbackFunction, baton_sp);
+
+ Error err (reader_sp->Initialize (CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback,
+ bp_options, // baton
+ eInputReaderGranularityLine, // token size, to pass to callback function
+ "DONE", // end token
+ "> ", // prompt
+ true)); // echo input
+ if (err.Success())
+ {
+ Debugger::GetSharedInstance().PushInputReader (reader_sp);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError (err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError("out of memory");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+}
+
+size_t
+CommandObjectBreakpointCommandAdd::GenerateBreakpointCommandCallback
+(
+ void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ if (out_fh)
+ {
+ ::fprintf (out_fh, "%s\n", g_reader_instructions);
+ if (reader->GetPrompt())
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ }
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderReactivate:
+ if (out_fh && reader->GetPrompt())
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ break;
+
+ case eInputReaderGotToken:
+ if (bytes && bytes_len && baton)
+ {
+ BreakpointOptions *bp_options = (BreakpointOptions *) baton;
+ if (bp_options)
+ {
+ Baton *bp_options_baton = bp_options->GetBaton();
+ if (bp_options_baton)
+ ((BreakpointOptions::CommandData *)bp_options_baton->m_data)->user_source.AppendString (bytes, bytes_len);
+ }
+ }
+ if (out_fh && !reader->IsDone() && reader->GetPrompt())
+ ::fprintf (out_fh, "%s", reader->GetPrompt());
+ break;
+
+ case eInputReaderDone:
+ break;
+ }
+
+ return bytes_len;
+}
+
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandRemove
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointCommandRemove::CommandObjectBreakpointCommandRemove () :
+ CommandObject ("remove",
+ "Remove the set of commands from a breakpoint.",
+ "breakpoint command remove <breakpoint-id>")
+{
+}
+
+CommandObjectBreakpointCommandRemove::~CommandObjectBreakpointCommandRemove ()
+{
+}
+
+bool
+CommandObjectBreakpointCommandRemove::Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ Target *target = context->GetTarget();
+
+ if (target == NULL)
+ {
+ result.AppendError ("There is not a current executable; there are no breakpoints from which to remove 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 removed");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (command.GetArgumentCount() == 0)
+ {
+ result.AppendError ("No breakpoint specified from which to remove the commands");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ BreakpointIDList valid_bp_ids;
+ CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ for (int i = 0; i < valid_bp_ids.Size(); ++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();
+}
+
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandList
+//-------------------------------------------------------------------------
+
+CommandObjectBreakpointCommandList::CommandObjectBreakpointCommandList () :
+ CommandObject ("List",
+ "List the script or set of commands to be executed when the breakpoint is hit.",
+ "breakpoint command list <breakpoint-id>")
+{
+}
+
+CommandObjectBreakpointCommandList::~CommandObjectBreakpointCommandList ()
+{
+}
+
+bool
+CommandObjectBreakpointCommandList::Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ Target *target = context->GetTarget();
+
+ 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::VerifyBreakpointIDs (command, target, result, &valid_bp_ids);
+
+ if (result.Succeeded())
+ {
+ for (int i = 0; i < valid_bp_ids.Size(); ++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)
+ {
+ 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->GetOptionsNoCopy();
+ 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());
+ 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 ("command",
+ "A set of commands for adding, removing and examining bits of code to be executed when the breakpoint is hit (breakpoint 'commmands').",
+ "command <sub-command> [<sub-command-options>] <breakpoint-id>")
+{
+ bool status;
+ CommandObjectSP add_command_object (new CommandObjectBreakpointCommandAdd ());
+ CommandObjectSP remove_command_object (new CommandObjectBreakpointCommandRemove ());
+ CommandObjectSP list_command_object (new CommandObjectBreakpointCommandList ());
+
+ add_command_object->SetCommandName ("breakpoint command add");
+ remove_command_object->SetCommandName ("breakpoint command remove");
+ list_command_object->SetCommandName ("breakpoint command list");
+
+ status = LoadSubCommand (add_command_object, "add", interpreter);
+ status = LoadSubCommand (remove_command_object, "remove", interpreter);
+ status = LoadSubCommand (list_command_object, "list", interpreter);
+}
+
+
+CommandObjectBreakpointCommand::~CommandObjectBreakpointCommand ()
+{
+}
+
+bool
+CommandObjectBreakpointCommand::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)
+ {
+ uint32_t num_commands = commands.GetSize();
+ CommandInterpreter &interpreter = Debugger::GetSharedInstance().GetCommandInterpreter();
+ CommandReturnObject result;
+ ExecutionContext exe_ctx = context->context;
+
+ FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+ FILE *err_fh = Debugger::GetSharedInstance().GetErrorFileHandle();
+
+
+ uint32_t i;
+ for (i = 0; i < num_commands; ++i)
+ {
+
+ // First time through we use the context from the stoppoint, after that we use whatever
+ // has been set by the previous command.
+
+ if (!interpreter.HandleCommand (commands.GetStringAtIndex(i), false, result, &exe_ctx))
+ break;
+
+ // FIXME: This isn't really the right way to do this. We should be able to peek at the public
+ // to see if there is any new events, but that is racey, since the internal process thread has to run and
+ // deliver the event to the public queue before a run will show up. So for now we check
+ // the internal thread state.
+
+ lldb::StateType internal_state = exe_ctx.process->GetPrivateState();
+ if (internal_state != eStateStopped)
+ {
+ if (i < num_commands - 1)
+ {
+ if (out_fh)
+ ::fprintf (out_fh, "Short-circuiting command execution because target state changed to %s."
+ " last command: \"%s\"\n", StateAsCString(internal_state),
+ commands.GetStringAtIndex(i));
+ }
+ break;
+ }
+
+ // First time through we use the context from the stoppoint, after that we use whatever
+ // has been set by the previous command.
+ exe_ctx = Debugger::GetSharedInstance().GetCurrentExecutionContext();
+
+
+ if (out_fh)
+ ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
+ if (err_fh)
+ ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
+ result.Clear();
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+
+ if (err_fh && !result.Succeeded() && i < num_commands)
+ ::fprintf (err_fh, "Attempt to execute '%s' failed.\n", commands.GetStringAtIndex(i));
+
+ if (out_fh)
+ ::fprintf (out_fh, "%s", result.GetErrorStream().GetData());
+
+ if (err_fh)
+ ::fprintf (err_fh, "%s", result.GetOutputStream().GetData());
+ }
+ return ret_value;
+}
+
diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.h b/lldb/source/Commands/CommandObjectBreakpointCommand.h
new file mode 100644
index 00000000000..2ba2c6075e8
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectBreakpointCommand.h
@@ -0,0 +1,169 @@
+//===-- CommandObjectBreakpointCommand.h ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectBreakpointCommand_h_
+#define liblldb_CommandObjectBreakpointCommand_h_
+
+// C Includes
+// C++ Includes
+
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-types.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordBreakpoint
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointCommand : public CommandObjectMultiword
+{
+public:
+ CommandObjectBreakpointCommand (CommandInterpreter *interpreter);
+
+ virtual
+ ~CommandObjectBreakpointCommand ();
+
+
+ static bool
+ BreakpointOptionsCallbackFunction (void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandAdd
+//-------------------------------------------------------------------------
+
+
+class CommandObjectBreakpointCommandAdd : public CommandObject
+{
+public:
+
+ CommandObjectBreakpointCommandAdd ();
+
+ virtual
+ ~CommandObjectBreakpointCommandAdd ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual Options *
+ GetOptions ();
+
+ void
+ CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
+ CommandReturnObject &result);
+
+ static size_t
+ GenerateBreakpointCommandCallback (void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len);
+
+ static bool
+ BreakpointOptionsCallbackFunction (void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::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;
+ };
+
+private:
+ CommandOptions m_options;
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandRemove
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointCommandRemove : public CommandObject
+{
+public:
+ CommandObjectBreakpointCommandRemove ();
+
+ virtual
+ ~CommandObjectBreakpointCommandRemove ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+private:
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectBreakpointCommandList
+//-------------------------------------------------------------------------
+
+class CommandObjectBreakpointCommandList : public CommandObject
+{
+public:
+ CommandObjectBreakpointCommandList ();
+
+ virtual
+ ~CommandObjectBreakpointCommandList ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+private:
+};
+
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectBreakpointCommand_h_
diff --git a/lldb/source/Commands/CommandObjectCall.cpp b/lldb/source/Commands/CommandObjectCall.cpp
new file mode 100644
index 00000000000..58d0a0e9f11
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectCall.cpp
@@ -0,0 +1,307 @@
+//===-- CommandObjectCall.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectCall.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/StackFrame.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// This command is a toy. I'm just using it to have a way to construct the arguments to
+// calling functions.
+//
+
+CommandObjectCall::CommandOptions::CommandOptions () :
+ Options()
+{
+ // Keep only one place to reset the values to their defaults
+ ResetOptionValues();
+}
+
+
+CommandObjectCall::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectCall::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'l':
+ if (language.SetLanguageFromCString (option_arg) == false)
+ {
+ error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg);
+ }
+ break;
+
+ case 'g':
+ debug = true;
+ break;
+
+ case 'f':
+ error = Args::StringToFormat(option_arg,format);
+ break;
+
+ case 'n':
+ noexecute = true;
+ break;
+
+ case 'a':
+ use_abi = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectCall::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+ language.Clear();
+ debug = false;
+ format = eFormatDefault;
+ show_types = true;
+ show_summary = true;
+ noexecute = false;
+ use_abi = false;
+}
+
+const lldb::OptionDefinition*
+CommandObjectCall::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+CommandObjectCall::CommandObjectCall () :
+ CommandObject (
+ "call",
+ "Call a function.",
+ "call <return_type> <function-name> [[<arg1-type> <arg1-value>] ... <argn-type> <argn-value>] [<cmd-options>]",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+{
+}
+
+CommandObjectCall::~CommandObjectCall ()
+{
+}
+
+Options *
+CommandObjectCall::GetOptions ()
+{
+ return &m_options;
+}
+
+bool
+CommandObjectCall::Execute
+(
+ Args &command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ ConstString target_triple;
+ int num_args = command.GetArgumentCount();
+
+ Target *target = context->GetTarget ();
+ if (target)
+ target->GetTargetTriple(target_triple);
+
+ if (!target_triple)
+ target_triple = Host::GetTargetTriple ();
+
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (exe_ctx.thread == NULL || exe_ctx.frame == NULL)
+ {
+ result.AppendError ("No currently selected thread and frame.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (num_args < 2)
+ {
+ result.AppendErrorWithFormat ("Invalid usage, should be: %s.\n", GetSyntax());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if ((num_args - 2) %2 != 0)
+ {
+ result.AppendErrorWithFormat ("Invalid usage - unmatched args & types, should be: %s.\n", GetSyntax());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (target_triple)
+ {
+ //const char *return_type = command.GetArgumentAtIndex(0);
+ const char *function_name = command.GetArgumentAtIndex(1);
+ // Look up the called function:
+
+ Function *target_fn = exe_ctx.frame->GetSymbolContext(eSymbolContextEverything).FindFunctionByName (function_name);
+
+ // FIXME: If target_fn is NULL, we should look up the name as a symbol and use it and the provided
+ // return type.
+
+ if (target_fn == NULL)
+ {
+ result.AppendErrorWithFormat ("Could not find function '%s'.\n", function_name);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ ValueList value_list;
+ // Okay, now parse arguments. For now we only accept basic types.
+ for (int i = 2; i < num_args; i+= 2)
+ {
+ const char *type_str = command.GetArgumentAtIndex(i);
+ const char *value_str = command.GetArgumentAtIndex(i + 1);
+ bool success;
+ if (strcmp(type_str, "int") == 0
+ || strcmp(type_str, "int32_t") == 0)
+ {
+ value_list.PushValue(Value(Args::StringToSInt32(value_str, 0, 0, &success)));
+ }
+ else if (strcmp (type_str, "int64_t") == 0)
+ {
+ value_list.PushValue(Value(Args::StringToSInt64(value_str, 0, 0, &success)));
+ }
+ else if (strcmp(type_str, "uint") == 0
+ || strcmp(type_str, "uint32_t") == 0)
+ {
+ value_list.PushValue(Value(Args::StringToUInt32(value_str, 0, 0, &success)));
+ }
+ else if (strcmp (type_str, "uint64_t") == 0)
+ {
+ value_list.PushValue(Value(Args::StringToUInt64(value_str, 0, 0, &success)));
+ }
+ else if (strcmp (type_str, "cstr") == 0)
+ {
+ Value val ((intptr_t)value_str);
+ val.SetValueType (Value::eValueTypeHostAddress);
+
+
+ void *cstr_type = target->GetScratchClangASTContext()->GetCStringType(true);
+ val.SetContext (Value::eContextTypeOpaqueClangQualType, cstr_type);
+ value_list.PushValue(val);
+
+ success = true;
+ }
+
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("Could not convert value: '%s' to type '%s'.\n", value_str, type_str);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ // Okay, we have the function and the argument list and the return type. Now make a ClangFunction object and
+ // run it:
+
+ StreamString errors;
+ ClangFunction clang_fun (target_triple.GetCString(), *target_fn, target->GetScratchClangASTContext(), value_list);
+ if (m_options.noexecute)
+ {
+ // Now write down the argument values for this call.
+ lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+ if (!clang_fun.InsertFunction (exe_ctx, args_addr, errors))
+ {
+ result.AppendErrorWithFormat("Error inserting function: '%s'.\n", errors.GetData());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ result.Succeeded();
+ return true;
+ }
+ }
+
+ ClangFunction::ExecutionResults return_status;
+ Value return_value;
+
+ if (m_options.use_abi)
+ {
+ return_status = clang_fun.ExecuteFunctionWithABI(exe_ctx, errors, return_value);
+ }
+ else
+ {
+ bool stop_others = true;
+ return_status = clang_fun.ExecuteFunction(exe_ctx, errors, stop_others, NULL, return_value);
+ }
+
+ // Now figure out what to do with the return value.
+ if (return_status == ClangFunction::eExecutionSetupError)
+ {
+ result.AppendErrorWithFormat("Error setting up function execution: '%s'.\n", errors.GetData());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else if (return_status != ClangFunction::eExecutionCompleted)
+ {
+ result.AppendWarningWithFormat("Interrupted while calling function: '%s'.\n", errors.GetData());
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+ else
+ {
+ // Now print out the result.
+ result.GetOutputStream().Printf("Return value: ");
+ return_value.Dump(&(result.GetOutputStream()));
+ result.Succeeded();
+ }
+
+ }
+ else
+ {
+ result.AppendError ("invalid target triple");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+}
+
+lldb::OptionDefinition
+CommandObjectCall::CommandOptions::g_option_table[] =
+{
+{ 0, true, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."},
+{ 0, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."},
+{ 0, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."},
+{ 0, false, "noexecute", 'n', no_argument, NULL, 0, "no execute", "Only JIT and copy the wrapper & arguments, but don't execute."},
+{ 0, false, "useabi", 'a', no_argument, NULL, 0, NULL, "Use the ABI instead of the JIT to marshall arguments."},
+{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
diff --git a/lldb/source/Commands/CommandObjectCall.h b/lldb/source/Commands/CommandObjectCall.h
new file mode 100644
index 00000000000..c051a142ece
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectCall.h
@@ -0,0 +1,84 @@
+//===-- CommandObjectCall.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectCall_h_
+#define liblldb_CommandObjectCall_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/Language.h"
+
+namespace lldb_private {
+
+class CommandObjectCall : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+ Language language;
+ lldb::Encoding encoding;
+ lldb::Format format;
+ bool debug;
+ bool show_types;
+ bool show_summary;
+ bool noexecute;
+ bool use_abi;
+ };
+
+ CommandObjectCall ();
+
+ virtual
+ ~CommandObjectCall ();
+
+ virtual
+ Options *
+ GetOptions ();
+
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual bool
+ WantsRawCommandString() { return false; }
+
+protected:
+
+ CommandOptions m_options;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectCall_h_
diff --git a/lldb/source/Commands/CommandObjectDelete.cpp b/lldb/source/Commands/CommandObjectDelete.cpp
new file mode 100644
index 00000000000..2fc072e2de4
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectDelete.cpp
@@ -0,0 +1,32 @@
+//===-- CommandObjectDelete.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectDelete.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectDelete
+//-------------------------------------------------------------------------
+
+CommandObjectDelete::CommandObjectDelete () :
+CommandObjectCrossref ("delete", "Lists the kinds of objects you can delete, and shows syntax for deleting them.", "delete")
+{
+}
+
+CommandObjectDelete::~CommandObjectDelete ()
+{
+}
+
+
diff --git a/lldb/source/Commands/CommandObjectDelete.h b/lldb/source/Commands/CommandObjectDelete.h
new file mode 100644
index 00000000000..f7d86b7aef7
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectDelete.h
@@ -0,0 +1,37 @@
+//===-- CommandObjectDelete.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectDelete_h_
+#define liblldb_CommandObjectDelete_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectCrossref.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectDelete
+//-------------------------------------------------------------------------
+
+class CommandObjectDelete : public CommandObjectCrossref
+{
+public:
+ CommandObjectDelete ();
+
+ virtual
+ ~CommandObjectDelete ();
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectDelete_h_
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp
new file mode 100644
index 00000000000..0985504e4ff
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -0,0 +1,431 @@
+//===-- CommandObjectDisassemble.cpp ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectDisassemble.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/SourceManager.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#define DEFAULT_DISASM_BYTE_SIZE 32
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectDisassemble::CommandOptions::CommandOptions () :
+ Options(),
+ m_func_name(),
+ m_load_addr()
+{
+ ResetOptionValues();
+}
+
+CommandObjectDisassemble::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'm':
+ show_mixed = true;
+ break;
+
+ case 'c':
+ num_lines_context = Args::StringToUInt32(option_arg, 0, 0);
+ break;
+
+ case 'b':
+ show_bytes = true;
+ break;
+
+ case 'a':
+ m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 0);
+ if (m_load_addr == LLDB_INVALID_ADDRESS)
+ m_load_addr = Args::StringToUInt64(optarg, LLDB_INVALID_ADDRESS, 16);
+
+ if (m_load_addr == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", optarg);
+ break;
+
+ case 'n':
+ m_func_name = option_arg;
+ break;
+
+ case 'r':
+ raw = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectDisassemble::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+ show_mixed = false;
+ show_bytes = false;
+ num_lines_context = 0;
+ m_func_name.clear();
+ m_load_addr = LLDB_INVALID_ADDRESS;
+}
+
+const lldb::OptionDefinition*
+CommandObjectDisassemble::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+lldb::OptionDefinition
+CommandObjectDisassemble::CommandOptions::g_option_table[] =
+{
+{ 0, false, "bytes", 'b', no_argument, NULL, 0, NULL, "Show opcode bytes when disassembling."},
+{ 0, false, "context", 'c', required_argument, NULL, 0, "<num-lines>", "Number of context lines of source to show."},
+{ 0, false, "mixed", 'm', no_argument, NULL, 0, NULL, "Enable mixed source and assembly display."},
+{ 0, false, "raw", 'r', no_argument, NULL, 0, NULL, "Print raw disassembly with no symbol information."},
+
+{ 1, false, "address", 'a', required_argument, NULL, 0, "<address>", "Address to start disassembling."},
+{ 1, false, "bytes", 'b', no_argument, NULL, 0, NULL, "Show opcode bytes when disassembling."},
+{ 1, false, "context", 'c', required_argument, NULL, 0, "<num-lines>", "Number of context lines of source to show."},
+{ 1, false, "mixed", 'm', no_argument, NULL, 0, NULL, "Enable mixed source and assembly display."},
+{ 1, false, "raw", 'r', no_argument, NULL, 0, NULL, "Print raw disassembly with no symbol information."},
+
+{ 2, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, "<function-name>", "Disassemble entire contents of the given function name."},
+{ 2, false, "bytes", 'b', no_argument, NULL, 0, NULL, "Show opcode bytes when disassembling."},
+{ 2, false, "context", 'c', required_argument, NULL, 0, "<num-lines>", "Number of context lines of source to show."},
+{ 2, false, "mixed", 'm', no_argument, NULL, 0, NULL, "Enable mixed source and assembly display."},
+{ 2, false, "raw", 'r', no_argument, NULL, 0, NULL, "Print raw disassembly with no symbol information."},
+
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+//-------------------------------------------------------------------------
+// CommandObjectDisassemble
+//-------------------------------------------------------------------------
+
+CommandObjectDisassemble::CommandObjectDisassemble () :
+ CommandObject ("disassemble",
+ "Disassemble bytes in the current function or anywhere in the inferior program.",
+ "disassemble [[<start-addr> [<end-addr>]] | <function-name>] [<cmd-options>]")
+{
+}
+
+CommandObjectDisassemble::~CommandObjectDisassemble()
+{
+}
+
+void
+CommandObjectDisassemble::Disassemble
+(
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result,
+ Disassembler *disassembler,
+ const SymbolContextList &sc_list
+)
+{
+ const size_t count = sc_list.GetSize();
+ SymbolContext sc;
+ AddressRange range;
+ for (size_t i=0; i<count; ++i)
+ {
+ if (sc_list.GetContextAtIndex(i, sc) == false)
+ break;
+ if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
+ {
+ lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(context->GetExecutionContext().process);
+ if (addr != LLDB_INVALID_ADDRESS)
+ {
+ lldb::addr_t end_addr = addr + range.GetByteSize();
+ Disassemble (context, interpreter, result, disassembler, addr, end_addr);
+ }
+ }
+ }
+}
+
+void
+CommandObjectDisassemble::Disassemble
+(
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result,
+ Disassembler *disassembler,
+ lldb::addr_t addr,
+ lldb::addr_t end_addr
+)
+{
+ if (addr == LLDB_INVALID_ADDRESS)
+ return;
+
+ if (end_addr == LLDB_INVALID_ADDRESS || addr >= end_addr)
+ end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+
+ ExecutionContext exe_ctx (context->GetExecutionContext());
+ DataExtractor data;
+ size_t bytes_disassembled = disassembler->ParseInstructions (&exe_ctx, eAddressTypeLoad, addr, end_addr - addr, data);
+ if (bytes_disassembled == 0)
+ {
+ // Nothing got disassembled...
+ }
+ else
+ {
+ // We got some things disassembled...
+ size_t num_instructions = disassembler->GetInstructionList().GetSize();
+ uint32_t offset = 0;
+ Stream &output_stream = result.GetOutputStream();
+ SymbolContext sc;
+ SymbolContext prev_sc;
+ AddressRange sc_range;
+ if (m_options.show_mixed)
+ output_stream.IndentMore ();
+
+ for (size_t i=0; i<num_instructions; ++i)
+ {
+ Disassembler::Instruction *inst = disassembler->GetInstructionList().GetInstructionAtIndex (i);
+ if (inst)
+ {
+ lldb::addr_t curr_addr = addr + offset;
+ if (m_options.show_mixed)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (!sc_range.ContainsLoadAddress (curr_addr, process))
+ {
+ prev_sc = sc;
+ Address curr_so_addr;
+ if (process && process->ResolveLoadAddress (curr_addr, curr_so_addr))
+ {
+ if (curr_so_addr.GetSection())
+ {
+ Module *module = curr_so_addr.GetSection()->GetModule();
+ uint32_t resolved_mask = module->ResolveSymbolContextForAddress(curr_so_addr, eSymbolContextEverything, sc);
+ if (resolved_mask)
+ {
+ sc.GetAddressRange (eSymbolContextEverything, sc_range);
+ if (sc != prev_sc)
+ {
+ if (offset != 0)
+ output_stream.EOL();
+
+ sc.DumpStopContext(&output_stream, process, curr_so_addr);
+ output_stream.EOL();
+ if (sc.comp_unit && sc.line_entry.IsValid())
+ {
+ interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbers (
+ sc.line_entry.file,
+ sc.line_entry.line,
+ m_options.num_lines_context,
+ m_options.num_lines_context,
+ m_options.num_lines_context ? "->" : "",
+ &output_stream);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if (m_options.show_mixed)
+ output_stream.IndentMore ();
+ output_stream.Indent();
+ size_t inst_byte_size = inst->GetByteSize();
+ inst->Dump(&output_stream, curr_addr, m_options.show_bytes ? &data : NULL, offset, exe_ctx, m_options.raw);
+ output_stream.EOL();
+ offset += inst_byte_size;
+ if (m_options.show_mixed)
+ output_stream.IndentLess ();
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (m_options.show_mixed)
+ output_stream.IndentLess ();
+
+ }
+}
+
+bool
+CommandObjectDisassemble::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ ArchSpec arch(target->GetArchitecture());
+ if (!arch.IsValid())
+ {
+ result.AppendError ("target needs valid architecure in order to be able to disassemble");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Disassembler *disassembler = Disassembler::FindPlugin(arch);
+
+ if (disassembler == NULL)
+ {
+ result.AppendErrorWithFormat ("Unable to find Disassembler plug-in for %s architecture.\n", arch.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+
+ lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t end_addr = LLDB_INVALID_ADDRESS;
+ ConstString name;
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0 && m_options.m_load_addr != LLDB_INVALID_ADDRESS)
+ {
+ addr = m_options.m_load_addr;
+ end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+ } else if (argc == 0 && !m_options.m_func_name.empty())
+ {
+ ConstString tmpname(m_options.m_func_name.c_str());
+ name = tmpname;
+ } else if (argc == 0)
+ {
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (exe_ctx.frame)
+ {
+ SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
+ if (sc.function)
+ {
+ addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(exe_ctx.process);
+ if (addr != LLDB_INVALID_ADDRESS)
+ end_addr = addr + sc.function->GetAddressRange().GetByteSize();
+ }
+ else if (sc.symbol && sc.symbol->GetAddressRangePtr())
+ {
+ addr = sc.symbol->GetAddressRangePtr()->GetBaseAddress().GetLoadAddress(exe_ctx.process);
+ if (addr != LLDB_INVALID_ADDRESS)
+ {
+ end_addr = addr + sc.symbol->GetAddressRangePtr()->GetByteSize();
+ if (addr == end_addr)
+ end_addr += DEFAULT_DISASM_BYTE_SIZE;
+ }
+ }
+ else
+ {
+ addr = exe_ctx.frame->GetPC().GetLoadAddress(exe_ctx.process);
+ if (addr != LLDB_INVALID_ADDRESS)
+ end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+ }
+ }
+ else
+ {
+ result.AppendError ("invalid frame");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else if (argc == 1)
+ {
+ const char *arg = command.GetArgumentAtIndex(0);
+ addr = Args::StringToAddress (arg);
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ // Lookup function or symbol name?
+ ConstString tmpname(arg);
+ name = tmpname;
+ }
+ else
+ {
+ end_addr = addr + DEFAULT_DISASM_BYTE_SIZE;
+ }
+ }
+ else if (argc >= 1 && argc <= 2)
+ {
+ addr = Args::StringToAddress (command.GetArgumentAtIndex(0));
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendErrorWithFormat ("Unable to parse address '%s'.\n", command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ end_addr = Args::StringToAddress (command.GetArgumentAtIndex(1), addr);
+ if (end_addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendErrorWithFormat ("Unable to parse address '%s'.\n", command.GetArgumentAtIndex(1));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ if (!name.IsEmpty())
+ {
+ SymbolContextList sc_list;
+
+ if (target->GetImages().FindFunctions(name, sc_list))
+ {
+ Disassemble (context, interpreter, result, disassembler, sc_list);
+ }
+ else if (target->GetImages().FindSymbolsWithNameAndType(name, eSymbolTypeCode, sc_list))
+ {
+ Disassemble (context, interpreter, result, disassembler, sc_list);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Unable to find symbol with name '%s'.\n", name.GetCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ if (addr < end_addr)
+ {
+ Disassemble (context, interpreter, result, disassembler, addr, end_addr);
+ }
+
+ if (addr == LLDB_INVALID_ADDRESS && name.IsEmpty())
+ {
+ result.AppendError ("No recognizable address of function name provided");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ {
+ return result.Succeeded();
+ }
+}
diff --git a/lldb/source/Commands/CommandObjectDisassemble.h b/lldb/source/Commands/CommandObjectDisassemble.h
new file mode 100644
index 00000000000..2cf800d2f59
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectDisassemble.h
@@ -0,0 +1,95 @@
+//===-- CommandObjectDisassemble.h ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectDisassemble_h_
+#define liblldb_CommandObjectDisassemble_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectDisassemble
+//-------------------------------------------------------------------------
+
+class CommandObjectDisassemble : public CommandObject
+{
+public:
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition*
+ GetDefinitions ();
+
+ bool show_mixed; // Show mixed source/assembly
+ bool show_bytes;
+ uint32_t num_lines_context;
+ bool raw;
+ std::string m_func_name;
+ lldb::addr_t m_load_addr;
+ static lldb::OptionDefinition g_option_table[];
+ };
+
+ CommandObjectDisassemble ();
+
+ virtual
+ ~CommandObjectDisassemble ();
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+protected:
+ CommandOptions m_options;
+
+ void
+ Disassemble (CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result,
+ Disassembler *disassembler,
+ lldb::addr_t addr,
+ lldb::addr_t end_addr);
+
+ void
+ Disassemble (CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result,
+ Disassembler *disassembler,
+ const SymbolContextList &sc_list);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectDisassemble_h_
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
new file mode 100644
index 00000000000..9afc8c0a1a3
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -0,0 +1,554 @@
+//===-- CommandObjectExpression.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectExpression.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangExpressionVariable.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "llvm/ADT/StringRef.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectExpression::CommandOptions::CommandOptions () :
+ Options()
+{
+ // Keep only one place to reset the values to their defaults
+ ResetOptionValues();
+}
+
+
+CommandObjectExpression::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectExpression::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'l':
+ if (language.SetLanguageFromCString (option_arg) == false)
+ {
+ error.SetErrorStringWithFormat("Invalid language option argument '%s'.\n", option_arg);
+ }
+ break;
+
+ case 'g':
+ debug = true;
+ break;
+
+ case 'f':
+ error = Args::StringToFormat(option_arg, format);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectExpression::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+ language.Clear();
+ debug = false;
+ format = eFormatDefault;
+ show_types = true;
+ show_summary = true;
+}
+
+const lldb::OptionDefinition*
+CommandObjectExpression::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+CommandObjectExpression::CommandObjectExpression () :
+ CommandObject (
+ "expression",
+ "Evaluate a C expression in the current program context, using variables currently in scope.",
+ "expression [<cmd-options>] <expr>"),
+ m_expr_line_count (0),
+ m_expr_lines ()
+{
+ SetHelpLong(
+"Examples: \n\
+\n\
+ expr my_struct->a = my_array[3] \n\
+ expr -f bin -- (index * 8) + 5 \n\
+ expr char c[] = \"foo\"; c[0]\n");
+}
+
+CommandObjectExpression::~CommandObjectExpression ()
+{
+}
+
+Options *
+CommandObjectExpression::GetOptions ()
+{
+ return &m_options;
+}
+
+
+bool
+CommandObjectExpression::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ return false;
+}
+
+
+size_t
+CommandObjectExpression::MultiLineExpressionCallback
+(
+ void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len
+)
+{
+ FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+ CommandObjectExpression *cmd_object_expr = (CommandObjectExpression *) baton;
+
+ switch (notification)
+ {
+ case eInputReaderActivate:
+ if (out_fh)
+ ::fprintf (out_fh, "%s\n", "Enter expressions, then terminate with an empty line to evaluate:");
+ // Fall through
+ case eInputReaderReactivate:
+ //if (out_fh)
+ // ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count);
+ break;
+
+ case eInputReaderDeactivate:
+ break;
+
+ case eInputReaderGotToken:
+ ++cmd_object_expr->m_expr_line_count;
+ if (bytes && bytes_len)
+ {
+ cmd_object_expr->m_expr_lines.append (bytes, bytes_len + 1);
+ }
+
+ if (bytes_len == 0)
+ reader->SetIsDone(true);
+ //else if (out_fh && !reader->IsDone())
+ // ::fprintf (out_fh, "%3u: ", cmd_object_expr->m_expr_line_count);
+ break;
+
+ case eInputReaderDone:
+ {
+ StreamFile out_stream(Debugger::GetSharedInstance().GetOutputFileHandle());
+ StreamFile err_stream(Debugger::GetSharedInstance().GetErrorFileHandle());
+ bool bare = false;
+ cmd_object_expr->EvaluateExpression (cmd_object_expr->m_expr_lines.c_str(),
+ bare,
+ out_stream,
+ err_stream);
+ }
+ break;
+ }
+
+ return bytes_len;
+}
+
+bool
+CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream)
+{
+ bool success = false;
+ ConstString target_triple;
+ Target *target = m_exe_ctx.target;
+ if (target)
+ target->GetTargetTriple(target_triple);
+
+ if (!target_triple)
+ target_triple = Host::GetTargetTriple ();
+
+
+ if (target_triple)
+ {
+ const bool show_types = m_options.show_types;
+ const bool show_summary = m_options.show_summary;
+ const bool debug = m_options.debug;
+
+ ClangExpressionDeclMap expr_decl_map(&m_exe_ctx);
+ ClangExpression clang_expr(target_triple.AsCString(), &expr_decl_map);
+
+ unsigned num_errors = 0;
+
+ if (bare)
+ num_errors = clang_expr.ParseBareExpression (llvm::StringRef(expr), error_stream);
+ else
+ num_errors = clang_expr.ParseExpression (expr, error_stream);
+
+ if (num_errors == 0)
+ {
+ StreamString dwarf_opcodes;
+ dwarf_opcodes.SetByteOrder(eByteOrderHost);
+ dwarf_opcodes.GetFlags().Set(Stream::eBinary);
+ ClangExpressionVariableList expr_local_vars;
+ clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes);
+
+ success = true;
+
+ DataExtractor dwarf_opcodes_data(dwarf_opcodes.GetData(), dwarf_opcodes.GetSize(), eByteOrderHost, 8);
+ DWARFExpression expr(dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize(), NULL);
+ expr.SetExpressionLocalVariableList(&expr_local_vars);
+ if (debug)
+ {
+ output_stream << "Expression parsed ok, dwarf opcodes:";
+ output_stream.IndentMore();
+ expr.GetDescription(&output_stream, lldb::eDescriptionLevelVerbose);
+ output_stream.IndentLess();
+ output_stream.EOL();
+ }
+
+ clang::ASTContext *ast_context = clang_expr.GetASTContext();
+ Value expr_result;
+ Error expr_error;
+ bool expr_success = expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error);
+ if (expr_success)
+ {
+ lldb::Format format = m_options.format;
+
+ // Resolve any values that are possible
+ expr_result.ResolveValue(&m_exe_ctx, ast_context);
+
+ if (expr_result.GetContextType() == Value::eContextTypeInvalid &&
+ expr_result.GetValueType() == Value::eValueTypeScalar &&
+ format == eFormatDefault)
+ {
+ // The expression result is just a scalar with no special formatting
+ expr_result.GetScalar().GetValue (&output_stream, show_types);
+ output_stream.EOL();
+ }
+ else
+ {
+ DataExtractor data;
+ expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0);
+ if (expr_error.Success())
+ {
+ if (format == eFormatDefault)
+ format = expr_result.GetValueDefaultFormat ();
+
+ void *clang_type = expr_result.GetValueOpaqueClangQualType();
+ if (clang_type)
+ {
+ if (show_types)
+ Type::DumpClangTypeName(&output_stream, clang_type);
+
+ Type::DumpValue (
+ &m_exe_ctx, // The execution context for memory and variable access
+ ast_context, // The ASTContext that the clang type belongs to
+ clang_type, // The opaque clang type we want to dump that value of
+ &output_stream, // Stream to dump to
+ format, // Format to use when dumping
+ data, // A buffer containing the bytes for the clang type
+ 0, // Byte offset within "data" where value is
+ data.GetByteSize(), // Size in bytes of the value we are dumping
+ 0, // Bitfield bit size
+ 0, // Bitfield bit offset
+ show_types, // Show types?
+ show_summary, // Show summary?
+ debug, // Debug logging output?
+ UINT32_MAX); // Depth to dump in case this is an aggregate type
+ }
+ else
+ {
+ data.Dump(&output_stream, // Stream to dump to
+ 0, // Byte offset within "data"
+ format, // Format to use when dumping
+ data.GetByteSize(), // Size in bytes of each item we are dumping
+ 1, // Number of items to dump
+ UINT32_MAX, // Number of items per line
+ LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context
+ 0, // Bitfield bit size
+ 0); // Bitfield bit offset
+ }
+ output_stream.EOL();
+ }
+ else
+ {
+ error_stream.Printf ("error: %s\n", expr_error.AsCString());
+ success = false;
+ }
+ }
+ }
+ else
+ {
+ error_stream.Printf ("error: %s\n", expr_error.AsCString());
+ }
+ }
+ }
+ else
+ {
+ error_stream.PutCString ("error: invalid target triple\n");
+ }
+
+ return success;
+}
+
+bool
+CommandObjectExpression::ExecuteRawCommandString
+(
+ const char *command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ ConstString target_triple;
+ Target *target = context->GetTarget ();
+ if (target)
+ target->GetTargetTriple(target_triple);
+
+ if (!target_triple)
+ target_triple = Host::GetTargetTriple ();
+
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+
+ Stream &output_stream = result.GetOutputStream();
+
+ m_options.ResetOptionValues();
+
+ const char * expr = NULL;
+
+ if (command[0] == '\0')
+ {
+ m_expr_lines.clear();
+ m_expr_line_count = 0;
+
+ InputReaderSP reader_sp (new InputReader());
+ if (reader_sp)
+ {
+ Error err (reader_sp->Initialize (CommandObjectExpression::MultiLineExpressionCallback,
+ this, // baton
+ eInputReaderGranularityLine, // token size, to pass to callback function
+ NULL, // end token
+ NULL, // prompt
+ true)); // echo input
+ if (err.Success())
+ {
+ Debugger::GetSharedInstance().PushInputReader (reader_sp);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError (err.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError("out of memory");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+
+ if (command[0] == '-')
+ {
+ // We have some options and these options MUST end with --.
+ const char *end_options = NULL;
+ const char *s = command;
+ while (s && s[0])
+ {
+ end_options = ::strstr (s, "--");
+ if (end_options)
+ {
+ end_options += 2; // Get past the "--"
+ if (::isspace (end_options[0]))
+ {
+ expr = end_options;
+ while (::isspace (*expr))
+ ++expr;
+ break;
+ }
+ }
+ s = end_options;
+ }
+
+ if (end_options)
+ {
+ Args args(command, end_options - command);
+ if (!ParseOptions(args, interpreter, result))
+ return false;
+ }
+ }
+
+ const bool show_types = m_options.show_types;
+ const bool show_summary = m_options.show_summary;
+ const bool debug = m_options.debug;
+
+
+ if (expr == NULL)
+ expr = command;
+
+ if (target_triple)
+ {
+ ClangExpressionDeclMap expr_decl_map(&exe_ctx);
+
+ ClangExpression clang_expr(target_triple.AsCString(), &expr_decl_map);
+
+ unsigned num_errors = clang_expr.ParseExpression (expr, result.GetErrorStream());
+
+ if (num_errors == 0)
+ {
+ StreamString dwarf_opcodes;
+ dwarf_opcodes.SetByteOrder(eByteOrderHost);
+ dwarf_opcodes.GetFlags().Set(Stream::eBinary);
+ ClangExpressionVariableList expr_local_vars;
+ clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes);
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+
+ DataExtractor dwarf_opcodes_data(dwarf_opcodes.GetData(), dwarf_opcodes.GetSize(), eByteOrderHost, 8);
+ DWARFExpression expr(dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize(), NULL);
+ expr.SetExpressionLocalVariableList(&expr_local_vars);
+ expr.SetExpressionDeclMap(&expr_decl_map);
+ if (debug)
+ {
+ output_stream << "Expression parsed ok, dwarf opcodes:";
+ output_stream.IndentMore();
+ expr.GetDescription(&output_stream, lldb::eDescriptionLevelVerbose);
+ output_stream.IndentLess();
+ output_stream.EOL();
+ }
+
+ clang::ASTContext *ast_context = clang_expr.GetASTContext();
+ Value expr_result;
+ Error expr_error;
+ bool expr_success = expr.Evaluate (&exe_ctx, ast_context, NULL, expr_result, &expr_error);
+ if (expr_success)
+ {
+ lldb::Format format = m_options.format;
+
+ // Resolve any values that are possible
+ expr_result.ResolveValue(&exe_ctx, ast_context);
+
+ if (expr_result.GetContextType() == Value::eContextTypeInvalid &&
+ expr_result.GetValueType() == Value::eValueTypeScalar &&
+ format == eFormatDefault)
+ {
+ // The expression result is just a scalar with no special formatting
+ expr_result.GetScalar().GetValue (&output_stream, show_types);
+ output_stream.EOL();
+ }
+ else
+ {
+ DataExtractor data;
+ expr_error = expr_result.GetValueAsData (&exe_ctx, ast_context, data, 0);
+ if (expr_error.Success())
+ {
+ if (format == eFormatDefault)
+ format = expr_result.GetValueDefaultFormat ();
+
+ void *clang_type = expr_result.GetValueOpaqueClangQualType();
+ if (clang_type)
+ {
+ if (show_types)
+ Type::DumpClangTypeName(&output_stream, clang_type);
+
+ Type::DumpValue (
+ &exe_ctx, // The execution context for memory and variable access
+ ast_context, // The ASTContext that the clang type belongs to
+ clang_type, // The opaque clang type we want to dump that value of
+ &output_stream, // Stream to dump to
+ format, // Format to use when dumping
+ data, // A buffer containing the bytes for the clang type
+ 0, // Byte offset within "data" where value is
+ data.GetByteSize(), // Size in bytes of the value we are dumping
+ 0, // Bitfield bit size
+ 0, // Bitfield bit offset
+ show_types, // Show types?
+ show_summary, // Show summary?
+ debug, // Debug logging output?
+ UINT32_MAX); // Depth to dump in case this is an aggregate type
+ }
+ else
+ {
+ data.Dump(&output_stream, // Stream to dump to
+ 0, // Byte offset within "data"
+ format, // Format to use when dumping
+ data.GetByteSize(), // Size in bytes of each item we are dumping
+ 1, // Number of items to dump
+ UINT32_MAX, // Number of items per line
+ LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context
+ 0, // Bitfield bit size
+ 0); // Bitfield bit offset
+ }
+ output_stream.EOL();
+ }
+ else
+ {
+ result.AppendError(expr_error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ {
+ result.AppendError (expr_error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("invalid target triple");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+}
+
+lldb::OptionDefinition
+CommandObjectExpression::CommandOptions::g_option_table[] =
+{
+{ 0, true, "language", 'l', required_argument, NULL, 0, "[c|c++|objc|objc++]", "Sets the language to use when parsing the expression."},
+{ 0, false, "format", 'f', required_argument, NULL, 0, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]", "Specify the format that the expression output should use."},
+{ 0, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable verbose debug logging of the expression parsing and evaluation."},
+{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
diff --git a/lldb/source/Commands/CommandObjectExpression.h b/lldb/source/Commands/CommandObjectExpression.h
new file mode 100644
index 00000000000..c67ba745af2
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectExpression.h
@@ -0,0 +1,105 @@
+//===-- CommandObjectExpression.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectExpression_h_
+#define liblldb_CommandObjectExpression_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/Language.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private {
+
+class CommandObjectExpression : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+ Language language;
+ lldb::Encoding encoding;
+ lldb::Format format;
+ bool debug;
+ bool show_types;
+ bool show_summary;
+ };
+
+ CommandObjectExpression ();
+
+ virtual
+ ~CommandObjectExpression ();
+
+ virtual
+ Options *
+ GetOptions ();
+
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual bool
+ WantsRawCommandString() { return true; }
+
+ virtual bool
+ ExecuteRawCommandString (const char *command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+protected:
+
+ static size_t
+ MultiLineExpressionCallback (void *baton,
+ InputReader *reader,
+ lldb::InputReaderAction notification,
+ const char *bytes,
+ size_t bytes_len);
+
+ bool
+ EvaluateExpression (const char *expr,
+ bool bare,
+ Stream &output_stream,
+ Stream &error_stream);
+
+ CommandOptions m_options;
+ ExecutionContext m_exe_ctx;
+ uint32_t m_expr_line_count;
+ std::string m_expr_lines; // Multi-line expression support
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectExpression_h_
diff --git a/lldb/source/Commands/CommandObjectFile.cpp b/lldb/source/Commands/CommandObjectFile.cpp
new file mode 100644
index 00000000000..01576c5b6d5
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectFile.cpp
@@ -0,0 +1,170 @@
+//===-- CommandObjectFile.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectFile.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectFile::CommandOptions::CommandOptions() :
+ Options (),
+ m_arch () // Breakpoint info defaults to brief descriptions
+{
+ BuildValidOptionSets();
+}
+
+CommandObjectFile::CommandOptions::~CommandOptions ()
+{
+}
+
+lldb::OptionDefinition
+CommandObjectFile::CommandOptions::g_option_table[] =
+{
+ { 0, false, "arch", 'a', required_argument, NULL, 0, "<arch>", "Specify the architecture to launch."},
+ { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+const lldb::OptionDefinition *
+CommandObjectFile::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+Error
+CommandObjectFile::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'a':
+ {
+ ArchSpec option_arch (option_arg);
+ if (option_arch.IsValid())
+ m_arch = option_arch;
+ else
+ error.SetErrorStringWithFormat ("Invalid arch string '%s'.\n", optarg);
+ }
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectFile::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+ m_arch.Clear();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectFile
+//-------------------------------------------------------------------------
+
+CommandObjectFile::CommandObjectFile() :
+ CommandObject ("file",
+ "Sets the file to be used as the main executable by the debugger.",
+ "file [<cmd-options>] <filename>")
+{
+}
+
+CommandObjectFile::~CommandObjectFile ()
+{
+}
+
+Options *
+CommandObjectFile::GetOptions ()
+{
+ return &m_options;
+}
+
+bool
+CommandObjectFile::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ const char *file_path = command.GetArgumentAtIndex(0);
+ Timer scoped_timer(__PRETTY_FUNCTION__, "(dbg) file '%s'", file_path);
+ const int argc = command.GetArgumentCount();
+ if (argc == 1)
+ {
+ FileSpec file_spec (file_path);
+
+ if (! file_spec.Exists())
+ {
+ result.AppendErrorWithFormat ("File '%s' does not exist.\n", file_path);
+ result.SetStatus (eReturnStatusFailed);
+ return result.Succeeded();
+ }
+
+ TargetSP target_sp;
+
+ ArchSpec arch;
+ if (m_options.m_arch.IsValid())
+ arch = m_options.m_arch;
+ else
+ {
+ arch = lldb_private::GetDefaultArchitecture ();
+ if (!arch.IsValid())
+ arch = LLDB_ARCH_DEFAULT;
+ }
+
+ Error error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file_spec, arch, NULL, true, target_sp);
+
+ if (error.Fail() && !m_options.m_arch.IsValid())
+ {
+ if (arch == LLDB_ARCH_DEFAULT_32BIT)
+ arch = LLDB_ARCH_DEFAULT_64BIT;
+ else
+ arch = LLDB_ARCH_DEFAULT_32BIT;
+ error = Debugger::GetSharedInstance().GetTargetList().CreateTarget (file_spec, arch, NULL, true, target_sp);
+ }
+
+ if (target_sp)
+ {
+ Debugger::GetSharedInstance().GetTargetList().SetCurrentTarget(target_sp.get());
+ result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, arch.AsCString());
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError(error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("'%s' takes exactly one executable path argument.\n", m_cmd_name.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+
+}
diff --git a/lldb/source/Commands/CommandObjectFile.h b/lldb/source/Commands/CommandObjectFile.h
new file mode 100644
index 00000000000..c44f610d970
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectFile.h
@@ -0,0 +1,79 @@
+//===-- CommandObjectFile.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectFile_h_
+#define liblldb_CommandObjectFile_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectFile
+//-------------------------------------------------------------------------
+
+class CommandObjectFile : public CommandObject
+{
+public:
+
+ CommandObjectFile ();
+
+ virtual
+ ~CommandObjectFile ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual Options *
+ GetOptions ();
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ ArchSpec m_arch;
+ };
+
+private:
+ CommandOptions m_options;
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectFile_h_
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
new file mode 100644
index 00000000000..78682dc0ca3
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -0,0 +1,171 @@
+//===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectFrame.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "CommandObjectThread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#pragma mark CommandObjectFrameInfo
+
+//-------------------------------------------------------------------------
+// CommandObjectFrameInfo
+//-------------------------------------------------------------------------
+
+class CommandObjectFrameInfo : public CommandObject
+{
+public:
+
+ CommandObjectFrameInfo () :
+ CommandObject ("frame info",
+ "Lists information about the currently selected frame in the current thread.",
+ "frame info",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+ {
+ }
+
+ ~CommandObjectFrameInfo ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (exe_ctx.frame)
+ {
+ exe_ctx.frame->Dump (&result.GetOutputStream(), true);
+ result.GetOutputStream().EOL();
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError ("no current frame");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+#pragma mark CommandObjectFrameSelect
+
+//-------------------------------------------------------------------------
+// CommandObjectFrameSelect
+//-------------------------------------------------------------------------
+
+class CommandObjectFrameSelect : public CommandObject
+{
+public:
+
+ CommandObjectFrameSelect () :
+ CommandObject ("frame select",
+ "Select the current frame by index in the current thread.",
+ "frame select <frame-index>",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+ {
+ }
+
+ ~CommandObjectFrameSelect ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ ExecutionContext exe_ctx (context->GetExecutionContext());
+ if (exe_ctx.thread)
+ {
+ if (command.GetArgumentCount() == 1)
+ {
+ const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
+
+ const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
+ const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
+ if (frame_idx < num_frames)
+ {
+ exe_ctx.thread->SetCurrentFrameByIndex (frame_idx);
+ exe_ctx.frame = exe_ctx.thread->GetCurrentFrame ().get();
+
+ if (exe_ctx.frame)
+ {
+ if (DisplayFrameForExecutionContext (exe_ctx.thread,
+ exe_ctx.frame,
+ interpreter,
+ result.GetOutputStream(),
+ true,
+ true,
+ 3,
+ 3))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ return result.Succeeded();
+ }
+ }
+ }
+ if (frame_idx == UINT32_MAX)
+ result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
+ else
+ result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
+ }
+ else
+ {
+ result.AppendError ("invalid arguments");
+ result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
+ }
+ }
+ else
+ {
+ result.AppendError ("no current thread");
+ }
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+};
+
+#pragma mark CommandObjectMultiwordFrame
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordFrame
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("frame",
+ "A set of commands for operating on the current thread's frames.",
+ "frame <subcommand> [<subcommand-options>]")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectFrameInfo ()), "info", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectFrameSelect ()), "select", interpreter);
+}
+
+CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
+{
+}
+
diff --git a/lldb/source/Commands/CommandObjectFrame.h b/lldb/source/Commands/CommandObjectFrame.h
new file mode 100644
index 00000000000..cb9cafe3a74
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectFrame.h
@@ -0,0 +1,40 @@
+//===-- CommandObjectFrame.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectFrame_h_
+#define liblldb_CommandObjectFrame_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordFrame
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordFrame : public CommandObjectMultiword
+{
+public:
+
+ CommandObjectMultiwordFrame (CommandInterpreter *interpreter);
+
+ virtual
+ ~CommandObjectMultiwordFrame ();
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectFrame_h_
diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp
new file mode 100644
index 00000000000..35e5b2ee5c4
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectHelp.cpp
@@ -0,0 +1,266 @@
+//===-- CommandObjectHelp.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectHelp.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectHelp
+//-------------------------------------------------------------------------
+
+CommandObjectHelp::CommandObjectHelp () :
+ CommandObject ("help",
+ "Shows a list of all debugger commands, or give details about specific commands.",
+ "help [<cmd-name>]")
+{
+}
+
+CommandObjectHelp::~CommandObjectHelp()
+{
+}
+
+
+bool
+CommandObjectHelp::OldExecute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ CommandObject::CommandMap::iterator pos;
+ CommandObject *cmd_obj;
+
+ const int argc = command.GetArgumentCount();
+ if (argc > 0)
+ {
+ cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex(0), false, false);
+ if (cmd_obj == NULL)
+ {
+ cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex(0), true, false);
+ if (cmd_obj != NULL)
+ {
+ StreamString alias_help_str;
+ interpreter->GetAliasHelp (command.GetArgumentAtIndex(0), cmd_obj->GetCommandName(), alias_help_str);
+ result.AppendMessageWithFormat ("'%s' is an alias for %s.\n", command.GetArgumentAtIndex (0),
+ alias_help_str.GetData());
+ }
+ }
+
+ if (cmd_obj)
+ {
+ Stream &output_strm = result.GetOutputStream();
+ if (cmd_obj->GetOptions() != NULL)
+ {
+ const char * long_help = cmd_obj->GetHelpLong();
+ if ((long_help!= NULL)
+ && strlen (long_help) > 0)
+ output_strm.Printf ("\n%s", cmd_obj->GetHelpLong());
+ else
+ output_strm.Printf ("\n%s\n", cmd_obj->GetHelp());
+ output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+ cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, cmd_obj);
+ }
+ else if (cmd_obj->IsMultiwordObject())
+ {
+ bool done = false;
+ if (argc > 1)
+ {
+ CommandObject::CommandMap::iterator pos;
+ std::string sub_command = command.GetArgumentAtIndex(1);
+ pos = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict.find(sub_command);
+ if (pos != ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict.end())
+ {
+ CommandObject *sub_cmd_obj = pos->second.get();
+ if (sub_cmd_obj->GetOptions() != NULL)
+ {
+ output_strm.Printf ("\n%s\n", sub_cmd_obj->GetHelp());
+ output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
+ sub_cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, sub_cmd_obj);
+ done = true;
+ }
+ else
+ {
+ output_strm.Printf ("\n%s\n", sub_cmd_obj->GetHelp());
+ output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
+ done = true;
+ }
+ }
+ }
+ if (!done)
+ {
+ output_strm.Printf ("%s\n", cmd_obj->GetHelp());
+ ((CommandObjectMultiword *) cmd_obj)->GenerateHelpText (result, interpreter);
+ }
+ }
+ else
+ {
+ const char *long_help = cmd_obj->GetHelpLong();
+ if ((long_help != NULL)
+ && (strlen (long_help) > 0))
+ output_strm.Printf ("\n%s", cmd_obj->GetHelpLong());
+ else
+ output_strm.Printf ("\n%s\n", cmd_obj->GetHelp());
+ output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+ }
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat
+ ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+ command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ interpreter->GetHelp(result);
+ }
+ return result.Succeeded();
+}
+
+bool
+CommandObjectHelp::Execute (Args &command, CommandContext *context, CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ CommandObject::CommandMap::iterator pos;
+ CommandObject *cmd_obj;
+ const int argc = command.GetArgumentCount ();
+
+ // 'help' doesn't take any options or arguments, other than command names. If argc is 0, we show the user
+ // all commands and aliases. Otherwise every argument must be the name of a command or a sub-command.
+
+ if (argc == 0)
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ interpreter->GetHelp (result); // General help, for ALL commands.
+ }
+ else
+ {
+ // Get command object for the first command argument. Only search built-in command dictionary.
+ cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex (0), false, false);
+ if (cmd_obj == NULL)
+ {
+ // That failed, so now search in the aliases dictionary, too.
+ cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex (0), true, false);
+ }
+
+ if (cmd_obj != NULL)
+ {
+ bool all_okay = true;
+ CommandObject *sub_cmd_obj = cmd_obj;
+ // Loop down through sub_command dictionaries until we find the command object that corresponds
+ // to the help command entered.
+ for (int i = 1; i < argc && all_okay; ++i)
+ {
+ std::string sub_command = command.GetArgumentAtIndex(i);
+ if (! sub_cmd_obj->IsMultiwordObject ())
+ {
+ all_okay = false;
+ }
+ else
+ {
+ pos = ((CommandObjectMultiword *) sub_cmd_obj)->m_subcommand_dict.find (sub_command);
+ if (pos != ((CommandObjectMultiword *) sub_cmd_obj)->m_subcommand_dict.end())
+ sub_cmd_obj = pos->second.get();
+ else
+ all_okay = false;
+ }
+ }
+
+ if (!all_okay || (sub_cmd_obj == NULL))
+ {
+ std::string cmd_string;
+ command.GetCommandString (cmd_string);
+ result.AppendErrorWithFormat
+ ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+ cmd_string.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ Stream &output_strm = result.GetOutputStream();
+ if (sub_cmd_obj->GetOptions() != NULL)
+ {
+ output_strm.Printf ("%s\n", sub_cmd_obj->GetHelp());
+ output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
+ sub_cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, sub_cmd_obj);
+ const char *long_help = sub_cmd_obj->GetHelpLong();
+ if ((long_help != NULL)
+ && (strlen (long_help) > 0))
+ output_strm.Printf ("\n%s", long_help);
+ }
+ else if (sub_cmd_obj->IsMultiwordObject())
+ {
+ output_strm.Printf ("%s\n", sub_cmd_obj->GetHelp());
+ ((CommandObjectMultiword *) sub_cmd_obj)->GenerateHelpText (result, interpreter);
+ }
+ else
+ {
+ const char *long_help = sub_cmd_obj->GetHelpLong();
+ if ((long_help != NULL)
+ && (strlen (long_help) > 0))
+ output_strm.Printf ("%s", long_help);
+ else
+ output_strm.Printf ("%s\n", sub_cmd_obj->GetHelp());
+ output_strm.Printf ("\nSyntax: %s\n", sub_cmd_obj->GetSyntax());
+ }
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat
+ ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+ command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+
+ return result.Succeeded();
+}
+
+int
+CommandObjectHelp::HandleCompletion
+(
+ Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches
+)
+{
+ // Return the completions of the commands in the help system:
+ if (cursor_index == 0)
+ {
+ return interpreter->HandleCompletionMatches(input, cursor_index, cursor_char_position, match_start_point, max_return_elements, matches);
+ }
+ else
+ {
+ CommandObject *cmd_obj = interpreter->GetCommandObject (input.GetArgumentAtIndex(0), true, false);
+ input.Shift();
+ cursor_index--;
+ return cmd_obj->HandleCompletion (input, cursor_index, cursor_char_position, match_start_point, max_return_elements, interpreter, matches);
+ }
+}
diff --git a/lldb/source/Commands/CommandObjectHelp.h b/lldb/source/Commands/CommandObjectHelp.h
new file mode 100644
index 00000000000..a8084aa704d
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectHelp.h
@@ -0,0 +1,59 @@
+//===-- CommandObjectHelp.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectHelp_h_
+#define liblldb_CommandObjectHelp_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectHelp
+//-------------------------------------------------------------------------
+
+class CommandObjectHelp : public CommandObject
+{
+public:
+
+ CommandObjectHelp ();
+
+ virtual
+ ~CommandObjectHelp ();
+
+ bool
+ OldExecute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual int
+ HandleCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectHelp_h_
diff --git a/lldb/source/Commands/CommandObjectImage.cpp b/lldb/source/Commands/CommandObjectImage.cpp
new file mode 100644
index 00000000000..ab728e9d32d
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectImage.cpp
@@ -0,0 +1,1419 @@
+//===-- CommandObjectImage.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectImage.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Static Helper functions
+//----------------------------------------------------------------------
+static void
+DumpModuleArchitecture (Stream &strm, Module *module, uint32_t width)
+{
+ if (module)
+ {
+ if (width)
+ strm.Printf("%-*s", width, module->GetArchitecture().AsCString());
+ else
+ strm.PutCString(module->GetArchitecture().AsCString());
+ }
+}
+
+static void
+DumpModuleUUID (Stream &strm, Module *module)
+{
+ module->GetUUID().Dump (&strm);
+}
+
+static uint32_t
+DumpCompileUnitLineTable
+(
+ CommandContext *context,
+ Stream &strm,
+ Module *module,
+ const FileSpec &file_spec,
+ bool load_addresses
+)
+{
+ uint32_t num_matches = 0;
+ if (module)
+ {
+ SymbolContextList sc_list;
+ num_matches = module->ResolveSymbolContextsForFileSpec (file_spec,
+ 0,
+ false,
+ eSymbolContextCompUnit,
+ sc_list);
+
+ for (uint32_t i=0; i<num_matches; ++i)
+ {
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(i, sc))
+ {
+ if (i > 0)
+ strm << "\n\n";
+
+ strm << "Line table for " << *dynamic_cast<FileSpec*> (sc.comp_unit) << " in `"
+ << module->GetFileSpec().GetFilename() << "\n";
+ LineTable *line_table = sc.comp_unit->GetLineTable();
+ if (line_table)
+ line_table->GetDescription (&strm, context->GetExecutionContext().process, lldb::eDescriptionLevelBrief);
+ else
+ strm << "No line table";
+ }
+ }
+ }
+ return num_matches;
+}
+
+static void
+DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+ if (file_spec_ptr)
+ {
+ if (width > 0)
+ {
+ char fullpath[PATH_MAX];
+ if (file_spec_ptr->GetPath(fullpath, sizeof(fullpath)))
+ {
+ strm.Printf("%-*s", width, fullpath);
+ return;
+ }
+ }
+ else
+ {
+ file_spec_ptr->Dump(&strm);
+ return;
+ }
+ }
+ // Keep the width spacing correct if things go wrong...
+ if (width > 0)
+ strm.Printf("%-*s", width, "");
+}
+
+static void
+DumpDirectory (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+ if (file_spec_ptr)
+ {
+ if (width > 0)
+ strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
+ else
+ file_spec_ptr->GetDirectory().Dump(&strm);
+ return;
+ }
+ // Keep the width spacing correct if things go wrong...
+ if (width > 0)
+ strm.Printf("%-*s", width, "");
+}
+
+static void
+DumpBasename (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
+{
+ if (file_spec_ptr)
+ {
+ if (width > 0)
+ strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
+ else
+ file_spec_ptr->GetFilename().Dump(&strm);
+ return;
+ }
+ // Keep the width spacing correct if things go wrong...
+ if (width > 0)
+ strm.Printf("%-*s", width, "");
+}
+
+
+static void
+DumpModuleSymtab (CommandContext *context, Stream &strm, Module *module)
+{
+ if (module)
+ {
+ ObjectFile *objfile = module->GetObjectFile ();
+ if (objfile)
+ {
+ Symtab *symtab = objfile->GetSymtab();
+ if (symtab)
+ symtab->Dump(&strm, context->GetExecutionContext().process);
+ }
+ }
+}
+
+static void
+DumpModuleSections (CommandContext *context, Stream &strm, Module *module)
+{
+ if (module)
+ {
+ ObjectFile *objfile = module->GetObjectFile ();
+ if (objfile)
+ {
+ SectionList *section_list = objfile->GetSectionList();
+ if (section_list)
+ section_list->Dump(&strm, context->GetExecutionContext().process, true);
+ }
+ }
+}
+
+static bool
+DumpModuleSymbolVendor (Stream &strm, Module *module)
+{
+ if (module)
+ {
+ SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
+ if (symbol_vendor)
+ {
+ symbol_vendor->Dump(&strm);
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+LookupAddressInModule (CommandContext *context, Stream &strm, Module *module, uint32_t resolve_mask, lldb::addr_t raw_addr, lldb::addr_t offset)
+{
+ if (module)
+ {
+ lldb::addr_t addr = raw_addr - offset;
+ Address so_addr;
+ SymbolContext sc;
+ Process *process = context->GetExecutionContext().process;
+ if (process && process->IsAlive())
+ {
+ if (!process->ResolveLoadAddress (addr, so_addr))
+ return false;
+ else if (so_addr.GetModule() != module)
+ return false;
+ }
+ else
+ {
+ if (!module->ResolveFileAddress (addr, so_addr))
+ return false;
+ }
+
+ // If an offset was given, print out the address we ended up looking up
+ if (offset)
+ strm.Printf("0x%llx: ", addr);
+
+ ExecutionContextScope *exe_scope = context->GetExecutionContext().GetBestExecutionContextScope();
+ if (so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset))
+ strm.PutCString(": ");
+ so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription);
+ return true;
+ }
+
+ return false;
+}
+
+static uint32_t
+LookupSymbolInModule (CommandContext *context, Stream &strm, Module *module, const char *name, bool name_is_regex)
+{
+ if (module)
+ {
+ SymbolContext sc;
+
+ ObjectFile *objfile = module->GetObjectFile ();
+ if (objfile)
+ {
+ Symtab *symtab = objfile->GetSymtab();
+ if (symtab)
+ {
+ uint32_t i;
+ std::vector<uint32_t> match_indexes;
+ ConstString symbol_name (name);
+ uint32_t num_matches = 0;
+ if (name_is_regex)
+ {
+ RegularExpression name_regexp(name);
+ num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType (name_regexp, eSymbolTypeAny,
+ match_indexes);
+ }
+ else
+ {
+ num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes);
+ }
+
+
+ if (num_matches > 0)
+ {
+ strm.Indent ();
+ strm.Printf("%u symbols match %s'%s' in ", num_matches,
+ name_is_regex ? "the regular expression " : "", name);
+ DumpFullpath (strm, &module->GetFileSpec(), 0);
+ strm.PutCString(":\n");
+ strm.IndentMore ();
+ Symtab::DumpSymbolHeader (&strm);
+ for (i=0; i < num_matches; ++i)
+ {
+ Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
+ strm.Indent ();
+ symbol->Dump (&strm, context->GetExecutionContext().process, i);
+ }
+ strm.IndentLess ();
+ return num_matches;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+static void
+DumpSymbolContextList (CommandContext *context, Stream &strm, SymbolContextList &sc_list, bool prepend_addr)
+{
+ strm.IndentMore ();
+ uint32_t i;
+ const uint32_t num_matches = sc_list.GetSize();
+
+ for (i=0; i<num_matches; ++i)
+ {
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(i, sc))
+ {
+ strm.Indent();
+ if (prepend_addr)
+ {
+ if (sc.line_entry.range.GetBaseAddress().IsValid())
+ {
+ lldb::addr_t vm_addr =
+ sc.line_entry.range.GetBaseAddress().GetLoadAddress(context->GetExecutionContext().process);
+ int addr_size = sizeof (addr_t);
+ Process *process = context->GetExecutionContext().process;
+ if (process)
+ addr_size = process->GetAddressByteSize();
+ if (vm_addr != LLDB_INVALID_ADDRESS)
+ strm.Address (vm_addr, addr_size);
+ else
+ sc.line_entry.range.GetBaseAddress().Dump (&strm, NULL, Address::DumpStyleSectionNameOffset);
+
+ strm.PutCString(" in ");
+ }
+ }
+ sc.DumpStopContext(&strm, context->GetExecutionContext().process, sc.line_entry.range.GetBaseAddress());
+ }
+ }
+ strm.IndentLess ();
+}
+
+static uint32_t
+LookupFunctionInModule (CommandContext *context, Stream &strm, Module *module, const char *name, bool name_is_regex)
+{
+ if (module && name && name[0])
+ {
+ SymbolContextList sc_list;
+
+ SymbolVendor *symbol_vendor = module->GetSymbolVendor();
+ if (symbol_vendor)
+ {
+ uint32_t num_matches = 0;
+ if (name_is_regex)
+ {
+ RegularExpression function_name_regex (name);
+ num_matches = symbol_vendor->FindFunctions(function_name_regex, true, sc_list);
+
+ }
+ else
+ {
+ ConstString function_name(name);
+ num_matches = symbol_vendor->FindFunctions(function_name, true, sc_list);
+ }
+
+ if (num_matches)
+ {
+ strm.Indent ();
+ strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
+ DumpFullpath (strm, &module->GetFileSpec(), 0);
+ strm.PutCString(":\n");
+ DumpSymbolContextList (context, strm, sc_list, true);
+ }
+ return num_matches;
+ }
+ }
+ return 0;
+}
+
+static uint32_t
+LookupFileAndLineInModule (CommandContext *context, Stream &strm, Module *module, const FileSpec &file_spec, uint32_t line, bool check_inlines)
+{
+ if (module && file_spec)
+ {
+ SymbolContextList sc_list;
+ const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
+ eSymbolContextEverything, sc_list);
+ if (num_matches > 0)
+ {
+ strm.Indent ();
+ strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
+ strm << file_spec;
+ if (line > 0)
+ strm.Printf (":%u", line);
+ strm << " in ";
+ DumpFullpath (strm, &module->GetFileSpec(), 0);
+ strm.PutCString(":\n");
+ DumpSymbolContextList (context, strm, sc_list, true);
+ return num_matches;
+ }
+ }
+ return 0;
+
+}
+
+
+//----------------------------------------------------------------------
+// Image symbol table dumping command
+//----------------------------------------------------------------------
+
+class CommandObjectImageDumpModuleList : public CommandObject
+{
+public:
+
+ CommandObjectImageDumpModuleList (const char *name,
+ const char *help,
+ const char *syntax) :
+ CommandObject (name, help, syntax)
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpModuleList ()
+ {
+ }
+
+ virtual int
+ HandleArgumentCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches)
+ {
+ // Arguments are the standard module completer.
+ std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+ completion_str.erase (cursor_char_position);
+
+ CommandCompletions::InvokeCommonCompletionCallbacks (CommandCompletions::eModuleCompletion,
+ completion_str.c_str(),
+ match_start_point,
+ max_return_elements,
+ interpreter,
+ NULL,
+ matches);
+ return matches.GetSize();
+ }
+};
+
+class CommandObjectImageDumpSourceFileList : public CommandObject
+{
+public:
+
+ CommandObjectImageDumpSourceFileList (const char *name,
+ const char *help,
+ const char *syntax) :
+ CommandObject (name, help, syntax)
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpSourceFileList ()
+ {
+ }
+
+ virtual int
+ HandleArgumentCompletion (Args &input,
+ int &cursor_index,
+ int &cursor_char_position,
+ OptionElementVector &opt_element_vector,
+ int match_start_point,
+ int max_return_elements,
+ CommandInterpreter *interpreter,
+ StringList &matches)
+ {
+ // Arguments are the standard source file completer.
+ std::string completion_str (input.GetArgumentAtIndex(cursor_index));
+ completion_str.erase (cursor_char_position);
+
+ CommandCompletions::InvokeCommonCompletionCallbacks (CommandCompletions::eSourceFileCompletion,
+ completion_str.c_str(),
+ match_start_point,
+ max_return_elements,
+ interpreter,
+ NULL,
+ matches);
+ return matches.GetSize();
+ }
+};
+
+
+class CommandObjectImageDumpSymtab : public CommandObjectImageDumpModuleList
+{
+public:
+ CommandObjectImageDumpSymtab () :
+ CommandObjectImageDumpModuleList ("image dump symtab",
+ "Dump the symbol table from one or more executable images.",
+ "image dump symtab [<file1> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpSymtab ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ uint32_t num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ result.GetOutputStream().Printf("Dumping symbol table for %u modules.\n", num_modules);
+ for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+ {
+ num_dumped++;
+ DumpModuleSymtab (context, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
+ }
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec image_file(arg_cstr);
+ ModuleList matching_modules;
+ const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+ if (num_matching_modules > 0)
+ {
+ for (size_t i=0; i<num_matching_modules; ++i)
+ {
+ Module *image_module = matching_modules.GetModulePointerAtIndex(i);
+ if (image_module)
+ {
+ num_dumped++;
+ DumpModuleSymtab (context, result.GetOutputStream(), image_module);
+ }
+ }
+ }
+ else
+ result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+ }
+ }
+
+ if (num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no matching executable images found");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ return result.Succeeded();
+ }
+
+};
+
+//----------------------------------------------------------------------
+// Image section dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpSections : public CommandObjectImageDumpModuleList
+{
+public:
+ CommandObjectImageDumpSections () :
+ CommandObjectImageDumpModuleList (
+ "image dump sections",
+ "Dump the sections from one or more executable images.",
+ "image dump sections [<file1> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpSections ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ uint32_t num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ result.GetOutputStream().Printf("Dumping sections for %u modules.\n", num_modules);
+ for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+ {
+ num_dumped++;
+ DumpModuleSections (context, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
+ }
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec image_file(arg_cstr);
+ ModuleList matching_modules;
+ const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+ if (num_matching_modules > 0)
+ {
+ for (size_t i=0; i<num_matching_modules; ++i)
+ {
+ Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+ if (image_module)
+ {
+ num_dumped++;
+ DumpModuleSections (context, result.GetOutputStream(), image_module);
+ }
+ }
+ }
+ else
+ result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+ }
+ }
+
+ if (num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no matching executable images found");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// Image debug symbol dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpSymfile : public CommandObjectImageDumpModuleList
+{
+public:
+ CommandObjectImageDumpSymfile () :
+ CommandObjectImageDumpModuleList ("image dump symfile",
+ "Dump the debug symbol file for one or more executable images.",
+ "image dump symfile [<file1> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpSymfile ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ uint32_t num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ result.GetOutputStream().Printf("Dumping debug symbols for %u modules.\n", num_modules);
+ for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+ {
+ if (DumpModuleSymbolVendor (result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx)))
+ num_dumped++;
+ }
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec image_file(arg_cstr);
+ ModuleList matching_modules;
+ const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+ if (num_matching_modules > 0)
+ {
+ for (size_t i=0; i<num_matching_modules; ++i)
+ {
+ Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+ if (image_module)
+ {
+ if (DumpModuleSymbolVendor (result.GetOutputStream(), image_module))
+ num_dumped++;
+ }
+ }
+ }
+ else
+ result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+ }
+ }
+
+ if (num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no matching executable images found");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// Image debug symbol dumping command
+//----------------------------------------------------------------------
+class CommandObjectImageDumpLineTable : public CommandObjectImageDumpSourceFileList
+{
+public:
+ CommandObjectImageDumpLineTable () :
+ CommandObjectImageDumpSourceFileList ("image dump line-table",
+ "Dump the debug symbol file for one or more executable images.",
+ "image dump line-table <file1> [<file2> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageDumpLineTable ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ uint32_t total_num_dumped = 0;
+
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+
+ if (command.GetArgumentCount() == 0)
+ {
+ result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ FileSpec file_spec(arg_cstr);
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ uint32_t num_dumped = 0;
+ for (uint32_t i = 0; i<num_modules; ++i)
+ {
+ if (DumpCompileUnitLineTable (context,
+ result.GetOutputStream(),
+ target->GetImages().GetModulePointerAtIndex(i),
+ file_spec,
+ exe_ctx.process != NULL && exe_ctx.process->IsAlive()))
+ num_dumped++;
+ }
+ if (num_dumped == 0)
+ result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
+ else
+ total_num_dumped += num_dumped;
+ }
+ }
+ }
+
+ if (total_num_dumped > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ {
+ result.AppendError ("no source filenames matched any command arguments");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// Dump multi-word command
+//----------------------------------------------------------------------
+class CommandObjectImageDump : public CommandObjectMultiword
+{
+public:
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectImageDump(CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("image dump",
+ "Dumps information in one or more executable images; 'line-table' expects a source file name",
+ "image dump [symtab|sections|symfile|line-table] [<file1> <file2> ...]")
+ {
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSymtab ()), "symtab", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSections ()), "sections", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpSymfile ()), "symfile", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDumpLineTable ()), "line-table", interpreter);
+ }
+
+ virtual
+ ~CommandObjectImageDump()
+ {
+ }
+};
+
+//----------------------------------------------------------------------
+// List images with associated information
+//----------------------------------------------------------------------
+class CommandObjectImageList : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options(),
+ m_format_array()
+ {
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ char short_option = (char) m_getopt_table[option_idx].val;
+ uint32_t width = 0;
+ if (option_arg)
+ width = strtoul (option_arg, NULL, 0);
+ m_format_array.push_back(std::make_pair(short_option, width));
+ Error error;
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ m_format_array.clear();
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection;
+ FormatWidthCollection m_format_array;
+ };
+
+ CommandObjectImageList () :
+ CommandObject (
+ "image list",
+ "List current executable and dependent shared library images.",
+ "image list [<cmd-options>]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageList ()
+ {
+ }
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ Stream &strm = result.GetOutputStream();
+
+ for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
+ {
+ Module *module = target->GetImages().GetModulePointerAtIndex(image_idx);
+ strm.Printf("[%3u] ", image_idx);
+
+ if (m_options.m_format_array.empty())
+ {
+ DumpFullpath(strm, &module->GetFileSpec(), 0);
+ }
+ else
+ {
+ const size_t num_entries = m_options.m_format_array.size();
+ for (size_t i=0; i<num_entries; ++i)
+ {
+ if (i > 0)
+ strm.PutChar(' ');
+ char format_char = m_options.m_format_array[i].first;
+ uint32_t width = m_options.m_format_array[i].second;
+ switch (format_char)
+ {
+ case 'a':
+ DumpModuleArchitecture (strm, module, width);
+ break;
+
+ case 'f':
+ DumpFullpath (strm, &module->GetFileSpec(), width);
+ break;
+
+ case 'd':
+ DumpDirectory (strm, &module->GetFileSpec(), width);
+ break;
+
+ case 'b':
+ DumpBasename (strm, &module->GetFileSpec(), width);
+ break;
+
+ case 's':
+ case 'S':
+ {
+ SymbolVendor *symbol_vendor = module->GetSymbolVendor();
+ if (symbol_vendor)
+ {
+ SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
+ if (symbol_file)
+ {
+ if (format_char == 'S')
+ DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+ else
+ DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+ break;
+ }
+ }
+ strm.Printf("%.*s", width, "<NONE>");
+ }
+ break;
+
+ case 'u':
+ DumpModuleUUID(strm, module);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ strm.EOL();
+ }
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ return result.Succeeded();
+ }
+protected:
+
+ CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectImageList::CommandOptions::g_option_table[] =
+{
+{ 0, false, "arch", 'a', optional_argument, NULL, 0, "<width>", "Display the architecture when listing images."},
+{ 0, false, "uuid", 'u', no_argument, NULL, 0, NULL, "Display the UUID when listing images."},
+{ 0, false, "fullpath", 'f', optional_argument, NULL, 0, "<width>", "Display the fullpath to the image object file."},
+{ 0, false, "directory", 'd', optional_argument, NULL, 0, "<width>", "Display the directory with optional width for the image object file."},
+{ 0, false, "basename", 'b', optional_argument, NULL, 0, "<width>", "Display the basename with optional width for the image object file."},
+{ 0, false, "symfile", 's', optional_argument, NULL, 0, "<width>", "Display the fullpath to the image symbol file with optional width."},
+{ 0, false, "symfile-basename", 'S', optional_argument, NULL, 0, "<width>", "Display the basename to the image symbol file with optional width."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+//----------------------------------------------------------------------
+// Lookup information in images
+//----------------------------------------------------------------------
+class CommandObjectImageLookup : public CommandObject
+{
+public:
+
+ enum
+ {
+ eLookupTypeInvalid = -1,
+ eLookupTypeAddress = 0,
+ eLookupTypeSymbol,
+ eLookupTypeFileLine, // Line is optional
+ eLookupTypeFunction,
+ kNumLookupTypes
+ };
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options()
+ {
+ ResetOptionValues();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'a':
+ m_type = eLookupTypeAddress;
+ m_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
+ if (m_addr == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", option_arg);
+ break;
+
+ case 'o':
+ m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
+ if (m_offset == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat ("Invalid offset string '%s'.\n", option_arg);
+ break;
+
+ case 's':
+ m_str = option_arg;
+ m_type = eLookupTypeSymbol;
+ break;
+
+ case 'f':
+ m_file.SetFile (option_arg);
+ m_type = eLookupTypeFileLine;
+ break;
+
+ case 'i':
+ m_check_inlines = false;
+ break;
+
+ case 'l':
+ m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX);
+ if (m_line_number == UINT32_MAX)
+ error.SetErrorStringWithFormat ("Invalid line number string '%s'.\n", option_arg);
+ else if (m_line_number == 0)
+ error.SetErrorString ("Zero is an invalid line number.");
+ m_type = eLookupTypeFileLine;
+ break;
+
+ case 'n':
+ m_str = option_arg;
+ m_type = eLookupTypeFunction;
+ break;
+
+ case 'r':
+ m_use_regex = true;
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ m_type = eLookupTypeInvalid;
+ m_str.clear();
+ m_file.Clear();
+ m_addr = LLDB_INVALID_ADDRESS;
+ m_offset = 0;
+ m_line_number = 0;
+ m_use_regex = false;
+ m_check_inlines = true;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+ int m_type; // Should be a eLookupTypeXXX enum after parsing options
+ std::string m_str; // Holds name lookup
+ FileSpec m_file; // Files for file lookups
+ lldb::addr_t m_addr; // Holds the address to lookup
+ lldb::addr_t m_offset; // Subtract this offset from m_addr before doing lookups.
+ uint32_t m_line_number; // Line number for file+line lookups
+ bool m_use_regex; // Name lookups in m_str are regular expressions.
+ bool m_check_inlines;// Check for inline entries when looking up by file/line.
+ };
+
+ CommandObjectImageLookup () :
+ CommandObject (
+ "image lookup",
+ "Look up information within executable and dependent shared library images.",
+ "image lookup [<cmd-options>] [<file1>...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectImageLookup ()
+ {
+ }
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+
+ bool
+ LookupInModule (CommandContext *context, Module *module, CommandReturnObject &result, bool &syntax_error)
+ {
+ switch (m_options.m_type)
+ {
+ case eLookupTypeAddress:
+ if (m_options.m_addr != LLDB_INVALID_ADDRESS)
+ {
+ if (LookupAddressInModule (context, result.GetOutputStream(), module, eSymbolContextEverything, m_options.m_addr, m_options.m_offset))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ break;
+
+ case eLookupTypeSymbol:
+ if (!m_options.m_str.empty())
+ {
+ if (LookupSymbolInModule (context, result.GetOutputStream(), module, m_options.m_str.c_str(), m_options.m_use_regex))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ break;
+
+ case eLookupTypeFileLine:
+ if (m_options.m_file)
+ {
+
+ if (LookupFileAndLineInModule (context,
+ result.GetOutputStream(),
+ module,
+ m_options.m_file,
+ m_options.m_line_number,
+ m_options.m_check_inlines))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ break;
+
+ case eLookupTypeFunction:
+ if (!m_options.m_str.empty())
+ {
+ if (LookupFunctionInModule (context,
+ result.GetOutputStream(),
+ module,
+ m_options.m_str.c_str(),
+ m_options.m_use_regex))
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ }
+ break;
+
+ default:
+ m_options.GenerateOptionUsage (result.GetErrorStream(), this);
+ syntax_error = true;
+ break;
+ }
+
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ bool syntax_error = false;
+ uint32_t i;
+ uint32_t num_successful_lookups = 0;
+ uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
+ result.GetOutputStream().SetAddressByteSize(addr_byte_size);
+ result.GetErrorStream().SetAddressByteSize(addr_byte_size);
+ // Dump all sections for all modules images
+
+ if (command.GetArgumentCount() == 0)
+ {
+ // Dump all sections for all modules images
+ const uint32_t num_modules = target->GetImages().GetSize();
+ if (num_modules > 0)
+ {
+ for (i = 0; i<num_modules && syntax_error == false; ++i)
+ {
+ if (LookupInModule (context, target->GetImages().GetModulePointerAtIndex(i), result, syntax_error))
+ {
+ result.GetOutputStream().EOL();
+ num_successful_lookups++;
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("the target has no associated executable images");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ // Dump specified images (by basename or fullpath)
+ const char *arg_cstr;
+ for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != NULL && syntax_error == false; ++i)
+ {
+ FileSpec image_file(arg_cstr);
+ ModuleList matching_modules;
+ const size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);
+
+ if (num_matching_modules > 0)
+ {
+ for (size_t i=0; i<num_matching_modules; ++i)
+ {
+ Module * image_module = matching_modules.GetModulePointerAtIndex(i);
+ if (image_module)
+ {
+ if (LookupInModule (context, image_module, result, syntax_error))
+ {
+ result.GetOutputStream().EOL();
+ num_successful_lookups++;
+ }
+ }
+ }
+ }
+ else
+ result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
+ }
+ }
+
+ if (num_successful_lookups > 0)
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ else
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+protected:
+
+ CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectImageLookup::CommandOptions::g_option_table[] =
+{
+{ 1, true, "address", 'a', required_argument, NULL, 0, "<addr>", "Lookup an address in one or more executable images."},
+{ 1, false, "offset", 'o', required_argument, NULL, 0, "<offset>", "When looking up an address subtract <offset> from any addresses before doing the lookup."},
+{ 2, true, "symbol", 's', required_argument, NULL, 0, "<name>", "Lookup a symbol by name in the symbol tables in one or more executable images."},
+{ 2, false, "regex", 'r', no_argument, NULL, 0, NULL, "The <name> argument for name lookups are regular expressions."},
+{ 3, true, "file", 'f', required_argument, NULL, 0, "<file>", "Lookup a file by fullpath or basename in one or more executable images."},
+{ 3, false, "line", 'l', required_argument, NULL, 0, "<line>", "Lookup a line number in a file (must be used in conjunction with --file)."},
+{ 3, false, "no-inlines", 'i', no_argument, NULL, 0, NULL, "Check inline line entries (must be used in conjunction with --file)."},
+{ 4, true, "function", 'n', required_argument, NULL, 0, "<name>", "Lookup a function by name in the debug symbols in one or more executable images."},
+{ 5, false, "regex", 'r', no_argument, NULL, 0, NULL, "The <name> argument for name lookups are regular expressions."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+
+
+//----------------------------------------------------------------------
+// CommandObjectImage constructor
+//----------------------------------------------------------------------
+CommandObjectImage::CommandObjectImage(CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("image",
+ "Access information for one or more executable images.",
+ "image [dump|list] ...")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageDump (interpreter)), "dump", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageList ()), "list", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectImageLookup ()), "lookup", interpreter);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectImage::~CommandObjectImage()
+{
+}
+
diff --git a/lldb/source/Commands/CommandObjectImage.h b/lldb/source/Commands/CommandObjectImage.h
new file mode 100644
index 00000000000..8863a3649a3
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectImage.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectImage.h ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectImage_h_
+#define liblldb_CommandObjectImage_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectImage
+//-------------------------------------------------------------------------
+
+class CommandObjectImage : public CommandObjectMultiword
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectImage(CommandInterpreter *interpreter);
+ virtual
+ ~CommandObjectImage();
+
+private:
+ //------------------------------------------------------------------
+ // For CommandObjectImage only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (CommandObjectImage);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectImage_h_
diff --git a/lldb/source/Commands/CommandObjectInfo.cpp b/lldb/source/Commands/CommandObjectInfo.cpp
new file mode 100644
index 00000000000..f817cc189b4
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectInfo.cpp
@@ -0,0 +1,32 @@
+//===-- CommandObjectInfo.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectInfo.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectInfo
+//-------------------------------------------------------------------------
+
+CommandObjectInfo::CommandObjectInfo () :
+CommandObjectCrossref ("info", "Lists the kinds of objects for which you can get information, and shows the syntax for doing so.", "info")
+{
+}
+
+CommandObjectInfo::~CommandObjectInfo ()
+{
+}
+
+
diff --git a/lldb/source/Commands/CommandObjectInfo.h b/lldb/source/Commands/CommandObjectInfo.h
new file mode 100644
index 00000000000..44f9bd1a394
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectInfo.h
@@ -0,0 +1,37 @@
+//===-- CommandObjectInfo.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectInfo_h_
+#define liblldb_CommandObjectInfo_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectCrossref.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectInfo
+//-------------------------------------------------------------------------
+
+class CommandObjectInfo : public CommandObjectCrossref
+{
+public:
+ CommandObjectInfo ();
+
+ virtual
+ ~CommandObjectInfo ();
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectInfo_h_
diff --git a/lldb/source/Commands/CommandObjectLog.cpp b/lldb/source/Commands/CommandObjectLog.cpp
new file mode 100644
index 00000000000..6b54badd7fc
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectLog.cpp
@@ -0,0 +1,452 @@
+//===-- CommandObjectLog.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectLog.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private-log.h"
+
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/FileSpec.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/Timer.h"
+
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static LogChannelSP
+GetLogChannelPluginForChannel (const char *channel)
+{
+ std::string log_channel_plugin_name(channel);
+ log_channel_plugin_name += LogChannel::GetPluginSuffix();
+ LogChannelSP log_channel_sp (LogChannel::FindPlugin (log_channel_plugin_name.c_str()));
+ return log_channel_sp;
+}
+
+
+class CommandObjectLogEnable : public CommandObject
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectLogEnable() :
+ CommandObject ("log enable",
+ "Enable logging for a single log channel.",
+ "log enable [<cmd-options>] <channel>")
+ {
+ }
+
+ virtual
+ ~CommandObjectLogEnable()
+ {
+ }
+
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ virtual bool
+ Execute (Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ if (args.GetArgumentCount() < 1)
+ {
+ result.GetErrorStream() << m_cmd_syntax.c_str();
+ }
+ else
+ {
+ Log::Callbacks log_callbacks;
+
+ std::string channel(args.GetArgumentAtIndex(0));
+ args.Shift (); // Shift off the channel
+ StreamSP log_stream_sp;
+
+ if (m_options.log_file.empty())
+ {
+ std::string log_file("<lldb.debugger>");
+ LogStreamMap::iterator pos = m_log_streams.find(log_file);
+ if (pos == m_log_streams.end())
+ {
+ log_stream_sp = Log::GetStreamForSTDOUT ();
+ if (log_stream_sp)
+ m_log_streams[log_file] = log_stream_sp;
+ }
+ else
+ log_stream_sp = pos->second;
+ }
+ else
+ {
+ LogStreamMap::iterator pos = m_log_streams.find(m_options.log_file);
+ if (pos == m_log_streams.end())
+ {
+ log_stream_sp.reset (new StreamFile (m_options.log_file.c_str(), "w"));
+ m_log_streams[m_options.log_file] = log_stream_sp;
+ }
+ else
+ log_stream_sp = pos->second;
+ }
+ assert (log_stream_sp.get());
+ uint32_t log_options = m_options.log_options;
+ if (log_options == 0)
+ log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE;
+ if (Log::GetLogChannelCallbacks (channel.c_str(), log_callbacks))
+ {
+ log_callbacks.enable (log_stream_sp, log_options, args, &result.GetErrorStream());
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ LogChannelSP log_channel_sp (GetLogChannelPluginForChannel(channel.c_str()));
+ if (log_channel_sp)
+ {
+ if (log_channel_sp->Enable (log_stream_sp, log_options, &result.GetErrorStream(), args))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Invalid log channel '%s'.\n", channel.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Invalid log channel '%s'.\n", channel.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ return result.Succeeded();
+ }
+
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options (),
+ log_file (),
+ log_options (0)
+ {
+ }
+
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'f': log_file = option_arg; break;
+ case 't': log_options |= LLDB_LOG_OPTION_THREADSAFE; break;
+ case 'v': log_options |= LLDB_LOG_OPTION_VERBOSE; break;
+ case 'g': log_options |= LLDB_LOG_OPTION_DEBUG; break;
+ case 's': log_options |= LLDB_LOG_OPTION_PREPEND_SEQUENCE; break;
+ case 'T': log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP; break;
+ case 'p': log_options |= LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD;break;
+ case 'n': log_options |= LLDB_LOG_OPTION_PREPEND_THREAD_NAME; break;
+ default:
+ error.SetErrorStringWithFormat ("Unrecognized option '%c'\n", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ log_file.clear();
+ log_options = 0;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ std::string log_file;
+ uint32_t log_options;
+ };
+
+protected:
+ typedef std::map<std::string, StreamSP> LogStreamMap;
+ CommandOptions m_options;
+ LogStreamMap m_log_streams;
+};
+
+lldb::OptionDefinition
+CommandObjectLogEnable::CommandOptions::g_option_table[] =
+{
+{ 0, false, "file", 'f', required_argument, NULL, 0, "<filename>", "Set the destination file to log to."},
+{ 0, false, "threadsafe", 't', no_argument, NULL, 0, NULL, "Enable thread safe logging to avoid interweaved log lines." },
+{ 0, false, "verbose", 'v', no_argument, NULL, 0, NULL, "Enable verbose logging." },
+{ 0, false, "debug", 'g', no_argument, NULL, 0, NULL, "Enable debug logging." },
+{ 0, false, "sequence", 's', no_argument, NULL, 0, NULL, "Prepend all log lines with an increasing integer sequence id." },
+{ 0, false, "timestamp", 'T', no_argument, NULL, 0, NULL, "Prepend all log lines with a timestamp." },
+{ 0, false, "pid-tid", 'p', no_argument, NULL, 0, NULL, "Prepend all log lines with the process and thread ID that generates the log line." },
+{ 0, false, "thread-name",'n', no_argument, NULL, 0, NULL, "Prepend all log lines with the thread name for the thread that generates the log line." },
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+class CommandObjectLogDisable : public CommandObject
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectLogDisable() :
+ CommandObject ("log disable",
+ "Disable one or more log channels.",
+ "log disable <channel> [<channel> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectLogDisable()
+ {
+ }
+
+ virtual bool
+ Execute (Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ const size_t argc = args.GetArgumentCount();
+ if (argc == 0)
+ {
+ result.GetErrorStream() << m_cmd_syntax.c_str();
+ }
+ else
+ {
+ for (size_t i=0; i<argc; ++i)
+ {
+ Log::Callbacks log_callbacks;
+
+ std::string channel(args.GetArgumentAtIndex(i));
+ if (Log::GetLogChannelCallbacks (channel.c_str(), log_callbacks))
+ {
+ log_callbacks.disable ();
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+ else if (channel == "all")
+ {
+ Log::DisableAllLogChannels();
+ }
+ else
+ {
+ LogChannelSP log_channel_sp (GetLogChannelPluginForChannel(channel.c_str()));
+ if (log_channel_sp)
+ {
+ log_channel_sp->Disable();
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
+ }
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectLogList : public CommandObject
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectLogList() :
+ CommandObject ("log list",
+ "List the log categories for one or more log channels.",
+ "log list <channel> [<channel> ...]")
+ {
+ }
+
+ virtual
+ ~CommandObjectLogList()
+ {
+ }
+
+ virtual bool
+ Execute (Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ const size_t argc = args.GetArgumentCount();
+ if (argc == 0)
+ {
+ Log::ListAllLogChannels (&result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ for (size_t i=0; i<argc; ++i)
+ {
+ Log::Callbacks log_callbacks;
+
+ std::string channel(args.GetArgumentAtIndex(i));
+ if (Log::GetLogChannelCallbacks (channel.c_str(), log_callbacks))
+ {
+ log_callbacks.list_categories (&result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+ else if (channel == "all")
+ {
+ Log::ListAllLogChannels (&result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ LogChannelSP log_channel_sp (GetLogChannelPluginForChannel(channel.c_str()));
+ if (log_channel_sp)
+ {
+ log_channel_sp->ListCategories(&result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ result.AppendErrorWithFormat("Invalid log channel '%s'.\n", args.GetArgumentAtIndex(0));
+ }
+ }
+ }
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectLogTimer : public CommandObject
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectLogTimer() :
+ CommandObject ("log timers",
+ "Enable, disable, dump, and reset LLDB internal performance timers.",
+ "log timers < enable | disable | dump | reset >")
+ {
+ }
+
+ virtual
+ ~CommandObjectLogTimer()
+ {
+ }
+
+ virtual bool
+ Execute (Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ const size_t argc = args.GetArgumentCount();
+ result.SetStatus(eReturnStatusFailed);
+
+ if (argc == 1)
+ {
+ const char *sub_command = args.GetArgumentAtIndex(0);
+
+ if (strcasecmp(sub_command, "enable") == 0)
+ {
+ Timer::SetDisplayDepth (UINT32_MAX);
+ result.SetStatus(eReturnStatusSuccessFinishNoResult);
+ }
+ else if (strcasecmp(sub_command, "disable") == 0)
+ {
+ Timer::DumpCategoryTimes (&result.GetOutputStream());
+ Timer::SetDisplayDepth (0);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+ else if (strcasecmp(sub_command, "dump") == 0)
+ {
+ Timer::DumpCategoryTimes (&result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+ else if (strcasecmp(sub_command, "reset") == 0)
+ {
+ Timer::ResetCategoryTimes ();
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+
+ }
+ if (!result.Succeeded())
+ {
+ result.AppendError("Missing subcommand");
+ result.AppendErrorWithFormat("Usage: %s\n", m_cmd_syntax.c_str());
+ }
+ return result.Succeeded();
+ }
+};
+
+//----------------------------------------------------------------------
+// CommandObjectLog constructor
+//----------------------------------------------------------------------
+CommandObjectLog::CommandObjectLog(CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("log",
+ "A set of commands for operating on logs.",
+ "log <command> [<command-options>]")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectLogEnable), "enable", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectLogDisable), "disable", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectLogList), "list", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectLogTimer), "timers", interpreter);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectLog::~CommandObjectLog()
+{
+}
+
+
+
+
diff --git a/lldb/source/Commands/CommandObjectLog.h b/lldb/source/Commands/CommandObjectLog.h
new file mode 100644
index 00000000000..a1ba258ea33
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectLog.h
@@ -0,0 +1,48 @@
+//===-- CommandObjectLog.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectLog_h_
+#define liblldb_CommandObjectLog_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectLog
+//-------------------------------------------------------------------------
+
+class CommandObjectLog : public CommandObjectMultiword
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectLog(CommandInterpreter *interpreter);
+
+ virtual
+ ~CommandObjectLog();
+
+private:
+ //------------------------------------------------------------------
+ // For CommandObjectLog only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (CommandObjectLog);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectLog_h_
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
new file mode 100644
index 00000000000..91abd81e9fd
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -0,0 +1,680 @@
+//===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectMemory.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Target/Process.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Read memory from the inferior process
+//----------------------------------------------------------------------
+class CommandObjectMemoryRead : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions () :
+ Options()
+ {
+ ResetOptionValues();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'f':
+ error = Args::StringToFormat (option_arg, m_format);
+
+ switch (m_format)
+ {
+ default:
+ break;
+
+ case eFormatBoolean:
+ if (m_byte_size == 0)
+ m_byte_size = 1;
+ if (m_num_per_line == 0)
+ m_num_per_line = 1;
+ break;
+
+ case eFormatCString:
+ if (m_num_per_line == 0)
+ m_num_per_line = 1;
+ break;
+
+ case eFormatPointer:
+ break;
+
+ case eFormatBinary:
+ case eFormatFloat:
+ case eFormatOctal:
+ case eFormatDecimal:
+ case eFormatEnum:
+ case eFormatUnicode16:
+ case eFormatUnicode32:
+ case eFormatUnsigned:
+ if (m_byte_size == 0)
+ m_byte_size = 4;
+ if (m_num_per_line == 0)
+ m_num_per_line = 1;
+ break;
+
+ case eFormatBytes:
+ case eFormatBytesWithASCII:
+ case eFormatChar:
+ case eFormatCharPrintable:
+ if (m_byte_size == 0)
+ m_byte_size = 1;
+ break;
+ case eFormatComplex:
+ if (m_byte_size == 0)
+ m_byte_size = 8;
+ break;
+ case eFormatHex:
+ if (m_byte_size == 0)
+ m_byte_size = 4;
+ break;
+
+ case eFormatVectorOfChar:
+ case eFormatVectorOfSInt8:
+ case eFormatVectorOfUInt8:
+ case eFormatVectorOfSInt16:
+ case eFormatVectorOfUInt16:
+ case eFormatVectorOfSInt32:
+ case eFormatVectorOfUInt32:
+ case eFormatVectorOfSInt64:
+ case eFormatVectorOfUInt64:
+ case eFormatVectorOfFloat32:
+ case eFormatVectorOfFloat64:
+ case eFormatVectorOfUInt128:
+ break;
+ }
+ break;
+
+ case 'l':
+ m_num_per_line = Args::StringToUInt32 (option_arg, 0);
+ if (m_num_per_line == 0)
+ error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
+ break;
+
+ case 'c':
+ m_count = Args::StringToUInt32 (option_arg, 0);
+ if (m_count == 0)
+ error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
+ break;
+
+ case 's':
+ m_byte_size = Args::StringToUInt32 (option_arg, 0);
+ if (m_byte_size == 0)
+ error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ m_format = eFormatBytesWithASCII;
+ m_byte_size = 0;
+ m_count = 0;
+ m_num_per_line = 0;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ lldb::Format m_format;
+ uint32_t m_byte_size;
+ uint32_t m_count;
+ uint32_t m_num_per_line;
+ };
+
+ CommandObjectMemoryRead () :
+ CommandObject ("memory read",
+ "Read memory from the process being debugged.",
+ "memory read [<cmd-options>] <start-addr> [<end-addr>]",
+ eFlagProcessMustBeLaunched)
+ {
+ }
+
+ virtual
+ ~CommandObjectMemoryRead ()
+ {
+ }
+
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError("need a process to read memory");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ const size_t argc = command.GetArgumentCount();
+
+ if (argc == 0 || argc > 2)
+ {
+ result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ size_t item_byte_size = m_options.m_byte_size;
+ if (item_byte_size == 0)
+ {
+ if (m_options.m_format == eFormatPointer)
+ item_byte_size = process->GetAddressByteSize();
+ else
+ item_byte_size = 1;
+ }
+
+ size_t item_count = m_options.m_count;
+
+ size_t num_per_line = m_options.m_num_per_line;
+ if (num_per_line == 0)
+ {
+ num_per_line = (16/item_byte_size);
+ if (num_per_line == 0)
+ num_per_line = 1;
+ }
+
+ size_t total_byte_size = m_options.m_count * item_byte_size;
+ if (total_byte_size == 0)
+ total_byte_size = 32;
+
+ lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
+
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (argc == 2)
+ {
+ lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
+ if (end_addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (end_addr <= addr)
+ {
+ result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (item_count != 0)
+ {
+ result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ total_byte_size = end_addr - addr;
+ item_count = total_byte_size / item_byte_size;
+ }
+ else
+ {
+ if (item_count == 0)
+ item_count = 32;
+ }
+
+ DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
+ Error error;
+ size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
+ if (bytes_read == 0)
+ {
+ result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
+ result.AppendError(error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ if (bytes_read < total_byte_size)
+ result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
+
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ DataExtractor data(data_sp, process->GetByteOrder(), process->GetAddressByteSize());
+
+ Stream &output_stream = result.GetOutputStream();
+ data.Dump(&output_stream,
+ 0,
+ m_options.m_format,
+ item_byte_size,
+ item_count,
+ num_per_line,
+ addr,
+ 0,
+ 0);
+ output_stream.EOL();
+ return true;
+ }
+
+protected:
+ CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectMemoryRead::CommandOptions::g_option_table[] =
+{
+ { 0, false, "format", 'f', required_argument, NULL, 0, "<format>", "The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."},
+ { 0, false, "size", 's', required_argument, NULL, 0, "<byte-size>","The size in bytes to use when displaying with the selected format."},
+ { 0, false, "num-per-line", 'l', required_argument, NULL, 0, "<N>", "The number of items per line to display."},
+ { 0, false, "count", 'c', required_argument, NULL, 0, "<N>", "The number of total items to display."},
+ { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//----------------------------------------------------------------------
+// Write memory to the inferior process
+//----------------------------------------------------------------------
+class CommandObjectMemoryWrite : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+ CommandOptions () :
+ Options()
+ {
+ ResetOptionValues();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+ switch (short_option)
+ {
+ case 'f':
+ error = Args::StringToFormat (option_arg, m_format);
+ break;
+
+ case 's':
+ m_byte_size = Args::StringToUInt32 (option_arg, 0);
+ if (m_byte_size == 0)
+ error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
+ break;
+
+
+ default:
+ error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ m_format = eFormatBytes;
+ m_byte_size = 1;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ lldb::Format m_format;
+ uint32_t m_byte_size;
+ };
+
+ CommandObjectMemoryWrite () :
+ CommandObject ("memory write",
+ "Write memory to the process being debugged.",
+ "memory write [<cmd-options>] <addr> [value1 value2 ...]",
+ eFlagProcessMustBeLaunched)
+ {
+ }
+
+ virtual
+ ~CommandObjectMemoryWrite ()
+ {
+ }
+
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ bool
+ UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
+ {
+ if (total_byte_size > 8)
+ return false;
+
+ if (total_byte_size == 8)
+ return true;
+
+ const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
+ return uval64 <= max;
+ }
+
+ bool
+ SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
+ {
+ if (total_byte_size > 8)
+ return false;
+
+ if (total_byte_size == 8)
+ return true;
+
+ const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
+ const int64_t min = ~(max);
+ return min <= sval64 && sval64 <= max;
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError("need a process to read memory");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ const size_t argc = command.GetArgumentCount();
+
+ if (argc < 2)
+ {
+ result.AppendErrorWithFormat ("%s takes an address and at least one value.\n", m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ size_t item_byte_size = m_options.m_byte_size ? m_options.m_byte_size : 1;
+ StreamString buffer (Stream::eBinary,
+ process->GetAddressByteSize(),
+ process->GetByteOrder());
+
+ lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
+
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ command.Shift(); // shift off the address argument
+ uint64_t uval64;
+ int64_t sval64;
+ bool success = false;
+ const uint32_t num_value_args = command.GetArgumentCount();
+ uint32_t i;
+ for (i=0; i<num_value_args; ++i)
+ {
+ const char *value_str = command.GetArgumentAtIndex(i);
+
+ switch (m_options.m_format)
+ {
+ case eFormatFloat: // TODO: add support for floats soon
+ case eFormatCharPrintable:
+ case eFormatBytesWithASCII:
+ case eFormatComplex:
+ case eFormatEnum:
+ case eFormatUnicode16:
+ case eFormatUnicode32:
+ case eFormatVectorOfChar:
+ case eFormatVectorOfSInt8:
+ case eFormatVectorOfUInt8:
+ case eFormatVectorOfSInt16:
+ case eFormatVectorOfUInt16:
+ case eFormatVectorOfSInt32:
+ case eFormatVectorOfUInt32:
+ case eFormatVectorOfSInt64:
+ case eFormatVectorOfUInt64:
+ case eFormatVectorOfFloat32:
+ case eFormatVectorOfFloat64:
+ case eFormatVectorOfUInt128:
+ result.AppendError("unsupported format for writing memory");
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+
+ case eFormatDefault:
+ case eFormatBytes:
+ case eFormatHex:
+ // Decode hex bytes
+ uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (!UIntValueIsValidForSize (uval64, item_byte_size))
+ {
+ result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ buffer.PutMaxHex64 (uval64, item_byte_size);
+ break;
+
+ case eFormatBoolean:
+ uval64 = Args::StringToBoolean(value_str, false, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ buffer.PutMaxHex64 (uval64, item_byte_size);
+ break;
+
+ case eFormatBinary:
+ uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (!UIntValueIsValidForSize (uval64, item_byte_size))
+ {
+ result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ buffer.PutMaxHex64 (uval64, item_byte_size);
+ break;
+
+ case eFormatChar:
+ case eFormatCString:
+ if (value_str[0])
+ {
+ size_t len = strlen (value_str);
+ // Include the NULL for C strings...
+ if (m_options.m_format == eFormatCString)
+ ++len;
+ Error error;
+ if (process->WriteMemory (addr, value_str, len, error) == len)
+ {
+ addr += len;
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ break;
+
+ case eFormatDecimal:
+ sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (!SIntValueIsValidForSize (sval64, item_byte_size))
+ {
+ result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ buffer.PutMaxHex64 (sval64, item_byte_size);
+ break;
+
+ case eFormatUnsigned:
+ uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (!UIntValueIsValidForSize (uval64, item_byte_size))
+ {
+ result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ buffer.PutMaxHex64 (uval64, item_byte_size);
+ break;
+
+ case eFormatOctal:
+ uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
+ if (!success)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ else if (!UIntValueIsValidForSize (uval64, item_byte_size))
+ {
+ result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ buffer.PutMaxHex64 (uval64, item_byte_size);
+ break;
+ }
+ }
+
+ if (!buffer.GetString().empty())
+ {
+ Error error;
+ if (process->WriteMemory (addr, buffer.GetString().data(), buffer.GetString().size(), error) == buffer.GetString().size())
+ return true;
+ else
+ {
+ result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+ }
+ return true;
+ }
+
+protected:
+ CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
+{
+ { 0, false, "format", 'f', required_argument, NULL, 0, "<format>", "The format value types that will be decoded and written to memory."},
+ { 0, false, "size", 's', required_argument, NULL, 0, "<byte-size>","The size in bytes of the values to write to memory."},
+ { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectMemory
+//-------------------------------------------------------------------------
+
+CommandObjectMemory::CommandObjectMemory (CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("memory",
+ "A set of commands for operating on a memory.",
+ "memory <subcommand> [<subcommand-options>]")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectMemoryRead ()), "read", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectMemoryWrite ()), "write", interpreter);
+}
+
+CommandObjectMemory::~CommandObjectMemory ()
+{
+}
diff --git a/lldb/source/Commands/CommandObjectMemory.h b/lldb/source/Commands/CommandObjectMemory.h
new file mode 100644
index 00000000000..a4665401510
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectMemory.h
@@ -0,0 +1,33 @@
+//===-- CommandObjectMemory.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectMemory_h_
+#define liblldb_CommandObjectMemory_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+class CommandObjectMemory : public CommandObjectMultiword
+{
+public:
+ CommandObjectMemory (CommandInterpreter *interpreter);
+
+ virtual
+ ~CommandObjectMemory ();
+};
+
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectMemory_h_
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
new file mode 100644
index 00000000000..ea0f6aff5eb
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -0,0 +1,833 @@
+//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectProcess.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/State.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessLaunch
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessLaunch : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options()
+ {
+ // Keep default values of all options in one place: ResetOptionValues ()
+ ResetOptionValues ();
+ }
+
+ ~CommandOptions ()
+ {
+ }
+
+ Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 's': stop_at_entry = true; break;
+ case 'e': stderr_path = option_arg; break;
+ case 'i': stdin_path = option_arg; break;
+ case 'o': stdout_path = option_arg; break;
+ case 'p': plugin_name = option_arg; break;
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+
+ }
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ stop_at_entry = false;
+ stdin_path.clear();
+ stdout_path.clear();
+ stderr_path.clear();
+ plugin_name.clear();
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ bool stop_at_entry;
+ std::string stderr_path;
+ std::string stdin_path;
+ std::string stdout_path;
+ std::string plugin_name;
+
+ };
+
+ CommandObjectProcessLaunch () :
+ CommandObject ("process launch",
+ "Launches the executable in the debugger.",
+ "process launch [<cmd-options>] [<arguments-for-running-the-program>]")
+ {
+ }
+
+
+ ~CommandObjectProcessLaunch ()
+ {
+ }
+
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ bool
+ Execute (Args& launch_args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target *target = context->GetTarget();
+ bool synchronous_execution = interpreter->GetSynchronous ();
+ // bool launched = false;
+ // bool stopped_after_launch = false;
+
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ // If our listener is NULL, users aren't allows to launch
+ Listener *listener = interpreter->GetListener();
+ if (listener == NULL)
+ {
+ result.AppendError ("operation not allowed through the command interpreter");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ char filename[PATH_MAX];
+ Module *exe_module = target->GetExecutableModule().get();
+ exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
+
+ Process *process = context->GetExecutionContext().process;
+ if (process)
+ {
+ if (process->IsAlive())
+ {
+ result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
+ process->GetID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ const char *plugin_name;
+ if (!m_options.plugin_name.empty())
+ plugin_name = m_options.plugin_name.c_str();
+ else
+ plugin_name = NULL;
+
+ process = target->CreateProcess (*listener, plugin_name).get();
+
+ const Args *environment = interpreter->GetEnvironmentVariables();
+ const Args *run_args = interpreter->GetProgramArguments();
+
+ // There are two possible sources of args to be passed to the process upon launching: Those the user
+ // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args).
+
+ // If launch_args is empty, use run_args.
+ if (launch_args.GetArgumentCount() == 0)
+ {
+ if (run_args != NULL)
+ launch_args.AppendArguments (*run_args);
+ }
+ else
+ {
+ // launch-args was not empty; use that, AND re-set run-args to contains launch-args values.
+ StateVariable *run_args_var = interpreter->GetStateVariable ("run-args");
+ if (run_args_var != NULL)
+ {
+ run_args_var->ArrayClearValues();
+ run_args_var->GetArgs().AppendArguments (launch_args);
+ }
+ }
+
+
+ if (process)
+ {
+ const char *archname = exe_module->GetArchitecture().AsCString();
+
+ const char * stdin_path = NULL;
+ const char * stdout_path = NULL;
+ const char * stderr_path = NULL;
+
+ if (!(m_options.stdin_path.empty() &&
+ m_options.stdout_path.empty() &&
+ m_options.stderr_path.empty()))
+ {
+ stdin_path = m_options.stdin_path.empty() ? "/dev/null" : m_options.stdin_path.c_str();
+ stdout_path = m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str();
+ stderr_path = m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str();
+ }
+
+ Error error (process->Launch (launch_args.GetConstArgumentVector(),
+ environment ? environment->GetConstArgumentVector() : NULL,
+ stdin_path,
+ stdout_path,
+ stderr_path));
+
+ if (error.Success())
+ {
+ result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname);
+ result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+ if (m_options.stop_at_entry == false)
+ {
+ StateType state = process->WaitForProcessToStop (NULL);
+
+ if (state == eStateStopped)
+ {
+ // Call continue_command.
+ CommandReturnObject continue_result;
+ interpreter->HandleCommand("process continue", false, continue_result);
+ }
+
+ if (synchronous_execution)
+ {
+ result.SetDidChangeProcessState (true);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Process launch failed: %s",
+ error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ return result.Succeeded();
+ }
+
+protected:
+
+ CommandOptions m_options;
+};
+
+
+lldb::OptionDefinition
+CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
+{
+{ 0, false, "stop-at-entry", 's', no_argument, NULL, 0, NULL, "Stop at the entry point of the program when launching a process."},
+{ 0, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."},
+{ 0, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."},
+{ 0, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."},
+{ 0, false, "plugin", 'p', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessAttach
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessAttach : public CommandObject
+{
+public:
+
+ CommandObjectProcessAttach () :
+ CommandObject ("process attach",
+ "Attaches to a process.",
+ "process attach <cmd-options>")
+ {
+ SetHelpLong("Currently, you must set the executable file before you can attach "
+ "to a process.\n");
+ }
+
+ ~CommandObjectProcessAttach ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ // If our listener is NULL, users aren't allows to launch
+ Listener *listener = interpreter->GetListener();
+ if (listener == NULL)
+ {
+ result.AppendError ("operation not allowed through the command interpreter");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ Process *process = context->GetExecutionContext().process;
+ if (process)
+ {
+ if (process->IsAlive())
+ {
+ result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", process->GetID());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ if (command.GetArgumentCount())
+ {
+ result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ const char *plugin_name = NULL;
+
+ if (!m_options.plugin_name.empty())
+ plugin_name = m_options.plugin_name.c_str();
+
+ process = target->CreateProcess (*listener, plugin_name).get();
+
+ if (process)
+ {
+ Error error;
+ int attach_pid = m_options.pid;
+
+ if (attach_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ error = process->Attach (attach_pid);
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
+ attach_pid,
+ error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else if (!m_options.name.empty())
+ {
+ error = process->Attach (m_options.name.c_str(), m_options.waitfor);
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+ }
+ else
+ {
+ if (m_options.waitfor)
+ result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
+ m_options.name.c_str(),
+ error.AsCString());
+ else
+ result.AppendErrorWithFormat ("Failed to a process named '%s': %s\n",
+ m_options.name.c_str(),
+ error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ }
+ return result.Succeeded();
+ }
+
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options()
+ {
+ // Keep default values of all options in one place: ResetOptionValues ()
+ ResetOptionValues ();
+ }
+
+ ~CommandOptions ()
+ {
+ }
+
+ Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+ bool success = false;
+ switch (short_option)
+ {
+ case 'p':
+ pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
+ if (!success || pid == LLDB_INVALID_PROCESS_ID)
+ {
+ error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
+ }
+ break;
+
+ case 'P':
+ plugin_name = option_arg;
+ break;
+
+ case 'n':
+ name.assign(option_arg);
+ break;
+
+ case 'w':
+ waitfor = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+ }
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ pid = LLDB_INVALID_PROCESS_ID;
+ name.clear();
+ waitfor = false;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ lldb::pid_t pid;
+ std::string plugin_name;
+ std::string name;
+ bool waitfor;
+ };
+
+protected:
+
+ CommandOptions m_options;
+};
+
+
+lldb::OptionDefinition
+CommandObjectProcessAttach::CommandOptions::g_option_table[] =
+{
+{ 0, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."},
+{ 0, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."},
+{ 1, true, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."},
+{ 1, false, "waitfor", 'w', no_argument, NULL, 0, NULL, "Wait for the the process with <process-name> to launch."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessContinue
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessContinue : public CommandObject
+{
+public:
+
+ CommandObjectProcessContinue () :
+ CommandObject ("process continue",
+ "Continues execution all threads in the current process.",
+ "process continue",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+ {
+ }
+
+
+ ~CommandObjectProcessContinue ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ bool synchronous_execution = interpreter->GetSynchronous ();
+
+ if (process == NULL)
+ {
+ result.AppendError ("no process to continue");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ StateType state = process->GetState();
+ if (state == eStateStopped)
+ {
+ if (command.GetArgumentCount() != 0)
+ {
+ result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const uint32_t num_threads = process->GetThreadList().GetSize();
+
+ // Set the actions that the threads should each take when resuming
+ for (uint32_t idx=0; idx<num_threads; ++idx)
+ {
+ process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
+ }
+
+ Error error(process->Resume());
+ if (error.Success())
+ {
+ result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
+ if (synchronous_execution)
+ {
+ StateType state = process->WaitForProcessToStop (NULL);
+
+ result.SetDidChangeProcessState (true);
+ result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
+ StateAsCString(state));
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessDetach
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessDetach : public CommandObject
+{
+public:
+
+ CommandObjectProcessDetach () :
+ CommandObject ("process detach",
+ "Detaches from the current process being debugged.",
+ "process detach",
+ eFlagProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectProcessDetach ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError ("must have a valid process in order to detach");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Error error (process->Detach());
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ return result.Succeeded();
+ }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessSignal
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessSignal : public CommandObject
+{
+public:
+
+ CommandObjectProcessSignal () :
+ CommandObject ("process signal",
+ "Sends a UNIX signal to the current process being debugged.",
+ "process signal <unix-signal-number>")
+ {
+ }
+
+ ~CommandObjectProcessSignal ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError ("no process to signal");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (command.GetArgumentCount() == 1)
+ {
+ int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
+ if (signo == -1)
+ {
+ result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ Error error (process->Signal (signo));
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
+ m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessInterrupt
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessInterrupt : public CommandObject
+{
+public:
+
+
+ CommandObjectProcessInterrupt () :
+ CommandObject ("process interrupt",
+ "Interrupts the current process being debugged.",
+ "process interrupt",
+ eFlagProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectProcessInterrupt ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError ("no process to halt");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (command.GetArgumentCount() == 0)
+ {
+ Error error(process->Halt ());
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+
+ // Maybe we should add a "SuspendThreadPlans so we
+ // can halt, and keep in place all the current thread plans.
+ process->GetThreadList().DiscardThreadPlans();
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
+ m_cmd_name.c_str(),
+ m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectProcessKill
+//-------------------------------------------------------------------------
+
+class CommandObjectProcessKill : public CommandObject
+{
+public:
+
+ CommandObjectProcessKill () :
+ CommandObject ("process kill",
+ "Terminates the current process being debugged.",
+ "process kill",
+ eFlagProcessMustBeLaunched)
+ {
+ }
+
+ ~CommandObjectProcessKill ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError ("no process to kill");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (command.GetArgumentCount() == 0)
+ {
+ Error error (process->Destroy());
+ if (error.Success())
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
+ m_cmd_name.c_str(),
+ m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordProcess
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("process",
+ "A set of commands for operating on a process.",
+ "process <subcommand> [<subcommand-options>]")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectProcessAttach ()), "attach", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectProcessLaunch ()), "launch", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectProcessContinue ()), "continue", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectProcessDetach ()), "detach", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectProcessSignal ()), "signal", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectProcessInterrupt ()), "interrupt", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectProcessKill ()), "kill", interpreter);
+}
+
+CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
+{
+}
+
diff --git a/lldb/source/Commands/CommandObjectProcess.h b/lldb/source/Commands/CommandObjectProcess.h
new file mode 100644
index 00000000000..9a8d59e70e6
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectProcess.h
@@ -0,0 +1,37 @@
+//===-- CommandObjectProcess.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectProcess_h_
+#define liblldb_CommandObjectProcess_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordProcess
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordProcess : public CommandObjectMultiword
+{
+public:
+ CommandObjectMultiwordProcess (CommandInterpreter *interpreter);
+
+ virtual
+ ~CommandObjectMultiwordProcess ();
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectProcess_h_
diff --git a/lldb/source/Commands/CommandObjectQuit.cpp b/lldb/source/Commands/CommandObjectQuit.cpp
new file mode 100644
index 00000000000..b66f4b108ff
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectQuit.cpp
@@ -0,0 +1,48 @@
+//===-- CommandObjectQuit.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectQuit.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "CommandInterpreter.h"
+#include "CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectQuit
+//-------------------------------------------------------------------------
+
+CommandObjectQuit::CommandObjectQuit () :
+ CommandObject ("quit", "Quits out of the LLDB debugger.", "quit")
+{
+}
+
+CommandObjectQuit::~CommandObjectQuit ()
+{
+}
+
+bool
+CommandObjectQuit::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ interpreter->BroadcastEvent (CommandInterpreter::eBroadcastBitQuitCommandReceived);
+ result.SetStatus (eReturnStatusQuit);
+ return true;
+}
+
diff --git a/lldb/source/Commands/CommandObjectQuit.h b/lldb/source/Commands/CommandObjectQuit.h
new file mode 100644
index 00000000000..a45d8a4b51b
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectQuit.h
@@ -0,0 +1,51 @@
+//===-- CommandObjectQuit.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectQuit_h_
+#define liblldb_CommandObjectQuit_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectQuit
+//-------------------------------------------------------------------------
+
+// SPECIAL NOTE!! The CommandObjectQuit is special, because the actual function to execute
+// when the user types 'quit' is passed (via function pointer) to the Command Interpreter when it
+// is constructed. The function pointer is then stored in this CommandObjectQuit, and is invoked
+// via the CommandObjectQuit::Execute function. This is the only command object that works this
+// way; it was done this way because different Command Interpreter callers may want or need different things
+// to be done in order to shut down properly.
+
+class CommandObjectQuit : public CommandObject
+{
+public:
+
+ CommandObjectQuit ();
+
+ virtual
+ ~CommandObjectQuit ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectQuit_h_
diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
new file mode 100644
index 00000000000..c4cb705c725
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -0,0 +1,231 @@
+//===-- CommandObjectRegister.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectRegister.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// "register read"
+//----------------------------------------------------------------------
+class CommandObjectRegisterRead : public CommandObject
+{
+public:
+ CommandObjectRegisterRead () :
+ CommandObject ("register read",
+ "Dump the one or more register values from the current frame.",
+ "register read [<reg-name1> [<reg-name2> [...]]]",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+ {
+ }
+
+ virtual
+ ~CommandObjectRegisterRead ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ StreamString &output_stream = result.GetOutputStream();
+ DataExtractor reg_data;
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
+
+ if (reg_context)
+ {
+ const RegisterInfo *reg_info = NULL;
+ if (command.GetArgumentCount() == 0)
+ {
+ uint32_t set_idx;
+ const uint32_t num_register_sets = reg_context->GetRegisterSetCount();
+ for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
+ {
+ uint32_t unavailable_count = 0;
+ const RegisterSet * const reg_set = reg_context->GetRegisterSet(set_idx);
+ output_stream.Printf ("%s:\n", reg_set->name);
+ output_stream.IndentMore ();
+ const uint32_t num_registers = reg_set->num_registers;
+ for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
+ {
+ uint32_t reg = reg_set->registers[reg_idx];
+ reg_info = reg_context->GetRegisterInfoAtIndex(reg);
+ if (reg_context->ReadRegisterBytes(reg, reg_data))
+ {
+ output_stream.Indent ();
+ output_stream.Printf ("%-12s = ", reg_info ? reg_info->name : "<INVALID REGINFO>");
+ reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+ output_stream.EOL();
+ }
+ else
+ {
+ ++unavailable_count;
+ }
+ }
+ if (unavailable_count)
+ {
+ output_stream.Indent ();
+ output_stream.Printf("%u registers were unavailable.\n", unavailable_count);
+ }
+ output_stream.IndentLess ();
+ output_stream.EOL();
+ }
+ }
+ else
+ {
+ const char *arg_cstr;
+ for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
+ {
+ reg_info = reg_context->GetRegisterInfoByName(arg_cstr);
+
+ if (reg_info)
+ {
+ output_stream.Printf("%-12s = ", reg_info->name);
+ if (reg_context->ReadRegisterBytes(reg_info->reg, reg_data))
+ {
+ reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
+ }
+ else
+ {
+ output_stream.PutCString ("error: unavailable");
+ }
+ output_stream.EOL();
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
+ }
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("no current frame");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+
+//----------------------------------------------------------------------
+// "register write"
+//----------------------------------------------------------------------
+class CommandObjectRegisterWrite : public CommandObject
+{
+public:
+ CommandObjectRegisterWrite () :
+ CommandObject ("register write",
+ "Modify a single register value.",
+ "register write <reg-name> <value>",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+ {
+ }
+
+ virtual
+ ~CommandObjectRegisterWrite ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ DataExtractor reg_data;
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
+
+ if (reg_context)
+ {
+ if (command.GetArgumentCount() != 2)
+ {
+ result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ const char *reg_name = command.GetArgumentAtIndex(0);
+ const char *value_str = command.GetArgumentAtIndex(1);
+ const RegisterInfo *reg_info = reg_context->GetRegisterInfoByName(reg_name);
+
+ if (reg_info)
+ {
+ Scalar scalar;
+ Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size));
+ if (error.Success())
+ {
+ if (reg_context->WriteRegisterValue(reg_info->reg, scalar))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
+ reg_name,
+ value_str,
+ error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("no current frame");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+
+//----------------------------------------------------------------------
+// CommandObjectRegister constructor
+//----------------------------------------------------------------------
+CommandObjectRegister::CommandObjectRegister(CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("register",
+ "Access thread registers.",
+ "register [read|write] ...")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectRegisterRead ()), "read", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectRegisterWrite ()), "write", interpreter);
+}
+
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectRegister::~CommandObjectRegister()
+{
+}
diff --git a/lldb/source/Commands/CommandObjectRegister.h b/lldb/source/Commands/CommandObjectRegister.h
new file mode 100644
index 00000000000..740bc5424e4
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectRegister.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectRegister.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectRegister_h_
+#define liblldb_CommandObjectRegister_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectRegister
+//-------------------------------------------------------------------------
+
+class CommandObjectRegister : public CommandObjectMultiword
+{
+public:
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ CommandObjectRegister(CommandInterpreter *interpreter);
+ virtual
+ ~CommandObjectRegister();
+
+private:
+ //------------------------------------------------------------------
+ // For CommandObjectRegister only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (CommandObjectRegister);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectRegister_h_
diff --git a/lldb/source/Commands/CommandObjectRemove.cpp b/lldb/source/Commands/CommandObjectRemove.cpp
new file mode 100644
index 00000000000..28736cd16ec
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectRemove.cpp
@@ -0,0 +1,89 @@
+//===-- CommandObjectRemove.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectRemove.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectRemove
+//-------------------------------------------------------------------------
+
+CommandObjectRemove::CommandObjectRemove () :
+ CommandObject ("remove",
+ "Allows the user to remove/delete user-defined command functions (script functions).",
+ "remove <command-name-to-be-removed>")
+{
+}
+
+CommandObjectRemove::~CommandObjectRemove()
+{
+}
+
+
+bool
+CommandObjectRemove::Execute (Args& args, CommandContext *context, CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ CommandObject::CommandMap::iterator pos;
+ CommandObject *cmd_obj;
+
+ if (args.GetArgumentCount() != 0)
+ {
+ const char *command_name = args.GetArgumentAtIndex(0);
+ cmd_obj = interpreter->GetCommandObject(command_name);
+ if (cmd_obj)
+ {
+ if (interpreter->CommandExists (command_name))
+ {
+ result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
+ command_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+
+ if (interpreter->RemoveUser (command_name) == false)
+ {
+ if (interpreter->UserCommandExists (command_name))
+ result.AppendErrorWithFormat ("Unknown error occurred; unable to remove command '%s'.\n",
+ command_name);
+ else
+ result.AppendErrorWithFormat ("'%s' is not a user-defined command/function name.\n",
+ command_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+ command_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("must call remove with a valid command");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return result.Succeeded();
+}
+
diff --git a/lldb/source/Commands/CommandObjectRemove.h b/lldb/source/Commands/CommandObjectRemove.h
new file mode 100644
index 00000000000..4b017a4fbb1
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectRemove.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectRemove.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectRemove_h_
+#define liblldb_CommandObjectRemove_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectRemove
+//-------------------------------------------------------------------------
+
+class CommandObjectRemove : public CommandObject
+{
+public:
+
+ CommandObjectRemove ();
+
+ virtual
+ ~CommandObjectRemove ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectRemove_h_
diff --git a/lldb/source/Commands/CommandObjectScript.cpp b/lldb/source/Commands/CommandObjectScript.cpp
new file mode 100644
index 00000000000..64864be8d09
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectScript.cpp
@@ -0,0 +1,149 @@
+//===-- CommandObjectScript.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectScript.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Interpreter/ScriptInterpreterPython.h"
+#include "lldb/Interpreter/ScriptInterpreterNone.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectScript
+//-------------------------------------------------------------------------
+
+CommandObjectScript::CommandObjectScript (ScriptLanguage script_lang) :
+ CommandObject ("script",
+ "Passes an expression to the script interpreter for evaluation and returns the results. Drops user into the interactive interpreter if no expressions are given.",
+ "script [<script-expressions-for-evaluation>]"),
+ m_script_lang (script_lang),
+ m_interpreter_ap ()
+{
+}
+
+CommandObjectScript::~CommandObjectScript ()
+{
+}
+
+bool
+CommandObjectScript::ExecuteRawCommandString
+(
+ const char *command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ std::string arg_str (command);
+
+ ScriptInterpreter *script_interpreter = GetInterpreter ();
+
+ if (script_interpreter == NULL)
+ {
+ result.AppendError("no script interpeter");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+ FILE *err_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+ if (out_fh && err_fh)
+ {
+ if (arg_str.empty())
+ script_interpreter->ExecuteInterpreterLoop (out_fh, err_fh);
+ else
+ script_interpreter->ExecuteOneLine (arg_str, out_fh, err_fh);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ if (out_fh == NULL)
+ result.AppendError("invalid output file handle");
+ else
+ result.AppendError("invalid error file handle");
+ }
+ return result.Succeeded();
+}
+
+bool
+CommandObjectScript::WantsRawCommandString()
+{
+ return true;
+}
+
+bool
+CommandObjectScript::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ std::string arg_str;
+ ScriptInterpreter *script_interpreter = GetInterpreter ();
+
+ if (script_interpreter == NULL)
+ {
+ result.AppendError("no script interpeter");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ const int argc = command.GetArgumentCount();
+ for (int i = 0; i < argc; ++i)
+ arg_str.append(command.GetArgumentAtIndex(i));
+
+
+ FILE *out_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+ FILE *err_fh = Debugger::GetSharedInstance().GetOutputFileHandle();
+ if (out_fh && err_fh)
+ {
+ if (arg_str.empty())
+ script_interpreter->ExecuteInterpreterLoop (out_fh, err_fh);
+ else
+ script_interpreter->ExecuteOneLine (arg_str, out_fh, err_fh);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ if (out_fh == NULL)
+ result.AppendError("invalid output file handle");
+ else
+ result.AppendError("invalid error file handle");
+ }
+ return result.Succeeded();
+}
+
+
+ScriptInterpreter *
+CommandObjectScript::GetInterpreter ()
+{
+ if (m_interpreter_ap.get() == NULL)
+ {
+ switch (m_script_lang)
+ {
+ case eScriptLanguagePython:
+ m_interpreter_ap.reset (new ScriptInterpreterPython ());
+ break;
+
+ case eScriptLanguageNone:
+ m_interpreter_ap.reset (new ScriptInterpreterNone ());
+ break;
+ }
+ }
+ return m_interpreter_ap.get();
+}
diff --git a/lldb/source/Commands/CommandObjectScript.h b/lldb/source/Commands/CommandObjectScript.h
new file mode 100644
index 00000000000..7cd57518ff7
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectScript.h
@@ -0,0 +1,58 @@
+//===-- CommandObjectScript.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectScript_h_
+#define liblldb_CommandObjectScript_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectScript
+//-------------------------------------------------------------------------
+
+class CommandObjectScript : public CommandObject
+{
+public:
+
+ CommandObjectScript (lldb::ScriptLanguage script_lang);
+
+ virtual
+ ~CommandObjectScript ();
+
+ bool WantsRawCommandString();
+
+ virtual bool
+ ExecuteRawCommandString (const char *command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ ScriptInterpreter *
+ GetInterpreter ();
+
+private:
+ lldb::ScriptLanguage m_script_lang;
+ std::auto_ptr<ScriptInterpreter> m_interpreter_ap;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectScript_h_
diff --git a/lldb/source/Commands/CommandObjectSelect.cpp b/lldb/source/Commands/CommandObjectSelect.cpp
new file mode 100644
index 00000000000..f357cd290a2
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSelect.cpp
@@ -0,0 +1,32 @@
+//===-- CommandObjectSelect.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSelect.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectSelect
+//-------------------------------------------------------------------------
+
+CommandObjectSelect::CommandObjectSelect () :
+ CommandObjectCrossref ("select", "Lists the kinds of objects you can select, and shows syntax for selecting them.", "select")
+{
+}
+
+CommandObjectSelect::~CommandObjectSelect ()
+{
+}
+
+
diff --git a/lldb/source/Commands/CommandObjectSelect.h b/lldb/source/Commands/CommandObjectSelect.h
new file mode 100644
index 00000000000..18a64eba276
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSelect.h
@@ -0,0 +1,37 @@
+//===-- CommandObjectSelect.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectSelect_h_
+#define liblldb_CommandObjectSelect_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectCrossref.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSelect
+//-------------------------------------------------------------------------
+
+class CommandObjectSelect : public CommandObjectCrossref
+{
+public:
+ CommandObjectSelect ();
+
+ virtual
+ ~CommandObjectSelect ();
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectSelect_h_
diff --git a/lldb/source/Commands/CommandObjectSet.cpp b/lldb/source/Commands/CommandObjectSet.cpp
new file mode 100644
index 00000000000..46ad049fd1b
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSet.cpp
@@ -0,0 +1,153 @@
+//===-- CommandObjectSet.cpp ------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSet.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectSet
+//-------------------------------------------------------------------------
+
+CommandObjectSet::CommandObjectSet () :
+ CommandObject ("set",
+ "Allows the user to set or change the value of a single debugger setting variable.",
+ "set <setting_name> <value>")
+{
+}
+
+CommandObjectSet::~CommandObjectSet()
+{
+}
+
+
+bool
+CommandObjectSet::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ CommandInterpreter::VariableMap::iterator pos;
+
+ const int argc = command.GetArgumentCount();
+
+ if (argc < 1)
+ {
+ result.AppendError ("'set' takes at least two arguments");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const char *var_name = command.GetArgumentAtIndex(0);
+ const char *var_value = command.GetArgumentAtIndex(1);
+
+ if (var_name == NULL || var_name[0] == '\0')
+ {
+ result.AppendError ("'set' command requires a valid variable name; No value supplied");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else if (var_value == NULL || var_value[0] == '\0')
+ {
+ // No value given: Check to see if we're trying to clear an array.
+ StateVariable *var = interpreter->GetStateVariable (var_name);
+ if (var != NULL
+ && var->GetType() == StateVariable::eTypeStringArray)
+ {
+ var->ArrayClearValues();
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendError ("'set' command requires a valid variable value; No value supplied");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ StateVariable *var = interpreter->GetStateVariable(var_name);
+ if (var == NULL)
+ {
+ result.AppendErrorWithFormat ("'%s' is not a settable internal variable.\n", var_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ if (var->GetType() == StateVariable::eTypeBoolean)
+ {
+ bool success = false;
+ bool new_value = Args::StringToBoolean (var_value, false, &success);
+
+ if (success)
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ if (!var->HasVerifyFunction() || var->VerifyValue (interpreter, (void *) &new_value, result))
+ var->SetBoolValue (new_value);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Invalid boolean string '%s'.\n", var_value);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else if (var->GetType() == StateVariable::eTypeInteger)
+ {
+ bool success = false;
+ int new_value = Args::StringToSInt32(var_value, -1, 0, &success);
+
+ if (success)
+ {
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ if (!var->HasVerifyFunction() || var->VerifyValue (interpreter, (void *) &new_value, result))
+ var->SetIntValue (new_value);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Invalid boolean string '%s'.\n", var_value);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else if (var->GetType() == StateVariable::eTypeString)
+ {
+ if (!var->HasVerifyFunction() || var->VerifyValue (interpreter, (void *) var_value, result))
+ var->SetStringValue (var_value);
+ }
+ else if (var->GetType() == StateVariable::eTypeStringArray)
+ {
+ if (var_value == NULL || var_value[0] == '\0')
+ var->ArrayClearValues ();
+ else
+ {
+ command.Shift(); // shift off variable name
+ var->ArrayClearValues(); // clear the old values
+ var->GetArgs().AppendArguments (command); // set the new values.
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Variable '%s' has unrecognized type.\n",
+ var->GetName());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ return result.Succeeded();
+}
+
diff --git a/lldb/source/Commands/CommandObjectSet.h b/lldb/source/Commands/CommandObjectSet.h
new file mode 100644
index 00000000000..1a3c3dfd1bc
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSet.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectSet.h --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectSet_h_
+#define liblldb_CommandObjectSet_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSet
+//-------------------------------------------------------------------------
+
+class CommandObjectSet : public CommandObject
+{
+public:
+
+ CommandObjectSet ();
+
+ virtual
+ ~CommandObjectSet ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectSet_h_
diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp
new file mode 100644
index 00000000000..078b699ffdb
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSettings.cpp
@@ -0,0 +1,62 @@
+//===-- CommandObjectSettings.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSettings.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectSettings
+//-------------------------------------------------------------------------
+
+CommandObjectSettings::CommandObjectSettings () :
+ CommandObject ("settings",
+ "Lists the debugger settings variables available to the user to 'set' or 'show'.",
+ "settings")
+{
+}
+
+CommandObjectSettings::~CommandObjectSettings()
+{
+}
+
+
+bool
+CommandObjectSettings::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ CommandInterpreter::VariableMap::iterator pos;
+
+ if (command.GetArgumentCount() != 0)
+ {
+ result.AppendError ("'settings' does not take any arguments");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ interpreter->ShowVariableHelp (result);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+
+ return result.Succeeded();
+}
+
diff --git a/lldb/source/Commands/CommandObjectSettings.h b/lldb/source/Commands/CommandObjectSettings.h
new file mode 100644
index 00000000000..674a98b8ca8
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSettings.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectSettings.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectSettings_h_
+#define liblldb_CommandObjectSettings_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSettings
+//-------------------------------------------------------------------------
+
+class CommandObjectSettings : public CommandObject
+{
+public:
+
+ CommandObjectSettings ();
+
+ virtual
+ ~CommandObjectSettings ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectSettings_h_
diff --git a/lldb/source/Commands/CommandObjectShow.cpp b/lldb/source/Commands/CommandObjectShow.cpp
new file mode 100644
index 00000000000..be6f6888a99
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectShow.cpp
@@ -0,0 +1,74 @@
+//===-- CommandObjectShow.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectShow.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectShow
+//-------------------------------------------------------------------------
+
+CommandObjectShow::CommandObjectShow () :
+ CommandObject ("show",
+ "Allows the user to see a single debugger setting variable and its value, or lists them all.",
+ "show [<setting-variable-name>]")
+{
+}
+
+CommandObjectShow::~CommandObjectShow()
+{
+}
+
+
+bool
+CommandObjectShow::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ CommandInterpreter::VariableMap::iterator pos;
+
+ if (command.GetArgumentCount())
+ {
+ // The user requested to see the value of a particular variable.
+
+ const char *var_name = command.GetArgumentAtIndex(0);
+ StateVariable *var = interpreter->GetStateVariable(var_name);
+ if (var)
+ {
+ var->AppendVariableInformation (result);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Unrecognized variable '%s'; cannot do 'show' command.\n", var_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ // The user didn't specify a particular variable, so show the values of all of them.
+ interpreter->ShowVariableValues(result);
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+
+ return result.Succeeded();
+}
diff --git a/lldb/source/Commands/CommandObjectShow.h b/lldb/source/Commands/CommandObjectShow.h
new file mode 100644
index 00000000000..460280a3c55
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectShow.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectShow.h -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectShow_h_
+#define liblldb_CommandObjectShow_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectShow
+//-------------------------------------------------------------------------
+
+class CommandObjectShow : public CommandObject
+{
+public:
+
+ CommandObjectShow ();
+
+ virtual
+ ~CommandObjectShow ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectShow_h_
diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp
new file mode 100644
index 00000000000..e2c3a0a143f
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSource.cpp
@@ -0,0 +1,127 @@
+//===-- CommandObjectSource.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSource.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/TargetList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+const char *k_space_characters = "\t\n\v\f\r ";
+
+//-------------------------------------------------------------------------
+// CommandObjectSource
+//-------------------------------------------------------------------------
+
+CommandObjectSource::CommandObjectSource() :
+ CommandObject ("source",
+ "Reads in debugger commands from the file <filename> and executes them.",
+ "source <filename>")
+{
+}
+
+CommandObjectSource::~CommandObjectSource ()
+{
+}
+
+bool
+CommandObjectSource::Execute
+(
+ Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ const int argc = args.GetArgumentCount();
+ if (argc == 1)
+ {
+ const char *filename = args.GetArgumentAtIndex(0);
+ bool success = true;
+
+ result.AppendMessageWithFormat ("Executing commands in '%s'.\n", filename);
+
+ FileSpec cmd_file (filename);
+ if (cmd_file.Exists())
+ {
+ STLStringArray commands;
+ success = cmd_file.ReadFileLines (commands);
+
+ STLStringArray::iterator pos = commands.begin();
+
+ // Trim out any empty lines or lines that start with the comment
+ // char '#'
+ while (pos != commands.end())
+ {
+ bool remove_string = false;
+ size_t non_space = pos->find_first_not_of (k_space_characters);
+ if (non_space == std::string::npos)
+ remove_string = true; // Empty line
+ else if ((*pos)[non_space] == '#')
+ remove_string = true; // Comment line that starts with '#'
+
+ if (remove_string)
+ pos = commands.erase(pos);
+ else
+ ++pos;
+ }
+
+ if (commands.size() > 0)
+ {
+ const size_t num_commands = commands.size();
+ size_t i;
+ for (i = 0; i<num_commands; ++i)
+ {
+ result.GetOutputStream().Printf("%s %s\n", interpreter->GetPrompt(), commands[i].c_str());
+ if (!interpreter->HandleCommand(commands[i].c_str(), false, result))
+ break;
+ }
+
+ if (i < num_commands)
+ {
+ result.AppendErrorWithFormat("Aborting source of '%s' after command '%s' failed.\n", filename, commands[i].c_str());
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ else
+ {
+ success = true;
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("File '%s' does not exist.\n", filename);
+ result.SetStatus (eReturnStatusFailed);
+ success = false;
+ }
+
+ if (success)
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("'%s' takes exactly one executable filename argument.\n", GetCommandName());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+
+}
diff --git a/lldb/source/Commands/CommandObjectSource.h b/lldb/source/Commands/CommandObjectSource.h
new file mode 100644
index 00000000000..416e3c02b2c
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSource.h
@@ -0,0 +1,48 @@
+//===-- CommandObjectSource.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectSource_h_
+#define liblldb_CommandObjectSource_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/STLUtils.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSource
+//-------------------------------------------------------------------------
+
+class CommandObjectSource : public CommandObject
+{
+public:
+
+ CommandObjectSource ();
+
+ virtual
+ ~CommandObjectSource ();
+
+ STLStringArray &
+ GetCommands ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectSource_h_
diff --git a/lldb/source/Commands/CommandObjectSourceFile.cpp b/lldb/source/Commands/CommandObjectSourceFile.cpp
new file mode 100644
index 00000000000..df70bc9aea3
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSourceFile.cpp
@@ -0,0 +1,206 @@
+//===-- CommandObjectSourceFile.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSourceFile.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Core/SourceManager.h"
+#include "lldb/Target/TargetList.h"
+#include "lldb/Interpreter/CommandCompletions.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CommandObjectSourceFile::CommandOptions::CommandOptions () :
+ Options()
+{
+}
+
+CommandObjectSourceFile::CommandOptions::~CommandOptions ()
+{
+}
+
+Error
+CommandObjectSourceFile::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+ const char short_option = g_option_table[option_idx].short_option;
+ switch (short_option)
+ {
+ case 'l':
+ start_line = Args::StringToUInt32 (option_arg, 0);
+ if (start_line == 0)
+ error.SetErrorStringWithFormat("Invalid line number: '%s'.\n", option_arg);
+ break;
+
+ case 'n':
+ num_lines = Args::StringToUInt32 (option_arg, 0);
+ if (num_lines == 0)
+ error.SetErrorStringWithFormat("Invalid line count: '%s'.\n", option_arg);
+ break;
+
+ case 'f':
+ file_name = option_arg;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+}
+
+void
+CommandObjectSourceFile::CommandOptions::ResetOptionValues ()
+{
+ Options::ResetOptionValues();
+
+ file_spec.Clear();
+ file_name.clear();
+ start_line = 0;
+ num_lines = 10;
+}
+
+const lldb::OptionDefinition*
+CommandObjectSourceFile::CommandOptions::GetDefinitions ()
+{
+ return g_option_table;
+}
+
+lldb::OptionDefinition
+CommandObjectSourceFile::CommandOptions::g_option_table[] =
+{
+{ 0, false, "line", 'l', required_argument, NULL, 0, "<line>", "The line number at which to start the display source."},
+{ 0, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<file>", "The file from which to display source."},
+{ 0, false, "count", 'n', required_argument, NULL, 0, "<count>", "The number of source lines to display."},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+
+//-------------------------------------------------------------------------
+// CommandObjectSourceFile
+//-------------------------------------------------------------------------
+
+CommandObjectSourceFile::CommandObjectSourceFile() :
+ CommandObject ("source-file",
+ "Display source files from the current executable's debug info.",
+ "source-file [<cmd-options>] [<filename>]")
+{
+}
+
+CommandObjectSourceFile::~CommandObjectSourceFile ()
+{
+}
+
+
+Options *
+CommandObjectSourceFile::GetOptions ()
+{
+ return &m_options;
+}
+
+
+bool
+CommandObjectSourceFile::Execute
+(
+ Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ const int argc = args.GetArgumentCount();
+
+ if (argc != 0)
+ {
+ result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName());
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (m_options.file_name.empty())
+ {
+ // Last valid source manager context, or the current frame if no
+ // valid last context in source manager.
+ // One little trick here, if you type the exact same list command twice in a row, it is
+ // more likely because you typed it once, then typed it again
+ if (m_options.start_line == 0)
+ {
+ if (interpreter->GetSourceManager().DisplayMoreWithLineNumbers (&result.GetOutputStream()))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ }
+ else
+ {
+ if (interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbersUsingLastFile(
+ m_options.start_line, // Line to display
+ 0, // Lines before line to display
+ m_options.num_lines, // Lines after line to display
+ "", // Don't mark "line"
+ &result.GetOutputStream()))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+
+ }
+ }
+ else
+ {
+ const char *filename = m_options.file_name.c_str();
+ Target *target = context->GetTarget();
+ if (target == NULL)
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+
+ bool check_inlines = false;
+ SymbolContextList sc_list;
+ size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename,
+ 0,
+ check_inlines,
+ eSymbolContextModule | eSymbolContextCompUnit,
+ sc_list);
+ if (num_matches > 0)
+ {
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(0, sc))
+ {
+ if (sc.comp_unit)
+ {
+ interpreter->GetSourceManager ().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
+ m_options.start_line, // Line to display
+ 0, // Lines before line to display
+ m_options.num_lines, // Lines after line to display
+ "", // Don't mark "line"
+ &result.GetOutputStream());
+
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+
+ }
+ }
+ }
+ }
+
+ return result.Succeeded();
+}
+
diff --git a/lldb/source/Commands/CommandObjectSourceFile.h b/lldb/source/Commands/CommandObjectSourceFile.h
new file mode 100644
index 00000000000..ba12f0f753c
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSourceFile.h
@@ -0,0 +1,80 @@
+//===-- CommandObjectSourceFile.h -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectSourceFile_h_
+#define liblldb_CommandObjectSourceFile_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Core/Options.h"
+#include "lldb/Core/FileSpec.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSourceFile
+//-------------------------------------------------------------------------
+
+class CommandObjectSourceFile : public CommandObject
+{
+public:
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions ();
+
+ virtual
+ ~CommandOptions ();
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ();
+
+ const lldb::OptionDefinition*
+ GetDefinitions ();
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ FileSpec file_spec;
+ std::string file_name;
+ uint32_t start_line;
+ uint32_t num_lines;
+ };
+
+ CommandObjectSourceFile ();
+
+ virtual
+ ~CommandObjectSourceFile ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual
+ Options *
+ GetOptions ();
+
+protected:
+ CommandOptions m_options;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectSourceFile_h_
diff --git a/lldb/source/Commands/CommandObjectStatus.cpp b/lldb/source/Commands/CommandObjectStatus.cpp
new file mode 100644
index 00000000000..501e0b23c84
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectStatus.cpp
@@ -0,0 +1,97 @@
+//===-- CommandObjectStatus.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectStatus.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "CommandObjectThread.h"
+
+#include "lldb/Core/State.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectStatus
+//-------------------------------------------------------------------------
+
+CommandObjectStatus::CommandObjectStatus () :
+ CommandObject ("status",
+ "Shows the current status and location of executing process.",
+ "status",
+ 0)
+{
+}
+
+CommandObjectStatus::~CommandObjectStatus()
+{
+}
+
+
+bool
+CommandObjectStatus::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ StreamString &output_stream = result.GetOutputStream();
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (exe_ctx.process)
+ {
+ const StateType state = exe_ctx.process->GetState();
+ if (StateIsStoppedState(state))
+ {
+ if (state == eStateExited)
+ {
+ int exit_status = exe_ctx.process->GetExitStatus();
+ const char *exit_description = exe_ctx.process->GetExitDescription();
+ output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
+ exe_ctx.process->GetID(),
+ exit_status,
+ exit_status,
+ exit_description ? exit_description : "");
+ }
+ else
+ {
+ output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
+ if (exe_ctx.thread == NULL)
+ exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
+ if (exe_ctx.thread != NULL)
+ {
+ DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true);
+ }
+ else
+ {
+ result.AppendError ("No valid thread found in current process.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("No current location or status available.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+}
+
diff --git a/lldb/source/Commands/CommandObjectStatus.h b/lldb/source/Commands/CommandObjectStatus.h
new file mode 100644
index 00000000000..da5fa7b7097
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectStatus.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectStatus.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectStatus_h_
+#define liblldb_CommandObjectStatus_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectStatus
+//-------------------------------------------------------------------------
+
+class CommandObjectStatus : public CommandObject
+{
+public:
+
+ CommandObjectStatus ();
+
+ ~CommandObjectStatus ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectStatus_h_
diff --git a/lldb/source/Commands/CommandObjectSyntax.cpp b/lldb/source/Commands/CommandObjectSyntax.cpp
new file mode 100644
index 00000000000..b1fc42f7637
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSyntax.cpp
@@ -0,0 +1,148 @@
+//===-- CommandObjectSyntax.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectSyntax.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectSyntax
+//-------------------------------------------------------------------------
+
+CommandObjectSyntax::CommandObjectSyntax () :
+ CommandObject ("syntax",
+ "Shows the correct syntax for a given debugger command.",
+ "syntax <command>")
+{
+}
+
+CommandObjectSyntax::~CommandObjectSyntax()
+{
+}
+
+
+bool
+CommandObjectSyntax::OldExecute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ CommandObject *cmd_obj;
+
+ if (command.GetArgumentCount() != 0)
+ {
+ cmd_obj = interpreter->GetCommandObject(command.GetArgumentAtIndex(0));
+ if (cmd_obj)
+ {
+ Stream &output_strm = result.GetOutputStream();
+ if (cmd_obj->GetOptions() != NULL)
+ {
+ output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+ //cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, cmd_obj);
+ output_strm.Printf ("(Try 'help %s' for more information on command options syntax.)\n",
+ cmd_obj->GetCommandName());
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' is not a known command.\n", command.GetArgumentAtIndex(0));
+ result.AppendError ("Try 'help' to see a current list of commands.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("Must call 'syntax' with a valid command.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+}
+
+bool
+CommandObjectSyntax::Execute (Args &command, CommandContext *context, CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ CommandObject::CommandMap::iterator pos;
+ CommandObject *cmd_obj;
+ const int argc = command.GetArgumentCount();
+
+ if (argc > 0)
+ {
+ cmd_obj = interpreter->GetCommandObject (command.GetArgumentAtIndex(0));
+ bool all_okay = true;
+ for (int i = 1; i < argc; ++i)
+ {
+ std::string sub_command = command.GetArgumentAtIndex (i);
+ if (! cmd_obj->IsMultiwordObject())
+ all_okay = false;
+ else
+ {
+ pos = ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict.find (sub_command);
+ if (pos != ((CommandObjectMultiword *) cmd_obj)->m_subcommand_dict.end())
+ cmd_obj = pos->second.get();
+ else
+ all_okay = false;
+ }
+ }
+
+ if (all_okay && (cmd_obj != NULL))
+ {
+ Stream &output_strm = result.GetOutputStream();
+ if (cmd_obj->GetOptions() != NULL)
+ {
+ output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+ //cmd_obj->GetOptions()->GenerateOptionUsage (output_strm, cmd_obj);
+ output_strm.Printf ("(Try 'help %s' for more information on command options syntax.)\n",
+ cmd_obj->GetCommandName());
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ output_strm.Printf ("\nSyntax: %s\n", cmd_obj->GetSyntax());
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ else
+ {
+ std::string cmd_string;
+ command.GetCommandString (cmd_string);
+ result.AppendErrorWithFormat ("'%s' is not a known command.\n", cmd_string.c_str());
+ result.AppendError ("Try 'help' to see a current list of commands.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("Must call 'syntax' with a valid command.");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return result.Succeeded();
+}
diff --git a/lldb/source/Commands/CommandObjectSyntax.h b/lldb/source/Commands/CommandObjectSyntax.h
new file mode 100644
index 00000000000..e5f5f4e544d
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectSyntax.h
@@ -0,0 +1,51 @@
+//===-- CommandObjectSyntax.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectSyntax_h_
+#define liblldb_CommandObjectSyntax_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectSyntax
+//-------------------------------------------------------------------------
+
+class CommandObjectSyntax : public CommandObject
+{
+public:
+
+ CommandObjectSyntax ();
+
+ virtual
+ ~CommandObjectSyntax ();
+
+ bool
+ OldExecute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectSyntax_h_
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
new file mode 100644
index 00000000000..5ea240e301f
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -0,0 +1,430 @@
+//===-- CommandObjectTarget.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectTarget.h"
+
+// C Includes
+#include <errno.h>
+#include <sys/errno.h>
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Interpreter/CommandContext.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+#pragma mark CommandObjectTargetImageSearchPaths
+
+class CommandObjectTargetImageSearchPathsAdd : public CommandObject
+{
+public:
+
+ CommandObjectTargetImageSearchPathsAdd () :
+ CommandObject ("target image-search-paths add",
+ "Add new image search paths substitution pairs to the current target.",
+ "target image-search-paths add <path-prefix> <new-path-prefix> [<path-prefix> <new-path-prefix>] ...")
+ {
+ }
+
+ ~CommandObjectTargetImageSearchPathsAdd ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target * target = context->GetTarget();
+ if (target)
+ {
+ uint32_t argc = command.GetArgumentCount();
+ if (argc & 1)
+ {
+ result.AppendError ("add requires an even number of arguments");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ for (uint32_t i=0; i<argc; i+=2)
+ {
+ const char *from = command.GetArgumentAtIndex(i);
+ const char *to = command.GetArgumentAtIndex(i+1);
+
+ if (from[0] && to[0])
+ {
+ bool last_pair = ((argc - i) == 2);
+ target->GetImageSearchPathList().Append(ConstString(from),
+ ConstString(to),
+ last_pair); // Notify if this is the last pair
+ }
+ else
+ {
+ if (from[0])
+ result.AppendError ("<path-prefix> can't be empty");
+ else
+ result.AppendError ("<new-path-prefix> can't be empty");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("invalid target");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectTargetImageSearchPathsClear : public CommandObject
+{
+public:
+
+ CommandObjectTargetImageSearchPathsClear () :
+ CommandObject ("target image-search-paths clear",
+ "Clears all current image search paths substitution pairs from the current target.",
+ "target image-search-paths clear")
+ {
+ }
+
+ ~CommandObjectTargetImageSearchPathsClear ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target * target = context->GetTarget();
+ if (target)
+ {
+ bool notify = true;
+ target->GetImageSearchPathList().Clear(notify);
+ }
+ else
+ {
+ result.AppendError ("invalid target");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectTargetImageSearchPathsInsert : public CommandObject
+{
+public:
+
+ CommandObjectTargetImageSearchPathsInsert () :
+ CommandObject ("target image-search-paths insert",
+ "Inserts a new image search paths substitution pair to the current target at the specified index.",
+ "target image-search-paths insert <index> <path-prefix> <new-path-prefix> [<path-prefix> <new-path-prefix>] ...")
+ {
+ }
+
+ ~CommandObjectTargetImageSearchPathsInsert ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target * target = context->GetTarget();
+ if (target)
+ {
+ uint32_t argc = command.GetArgumentCount();
+ // check for at least 3 arguments and an odd nubmer of parameters
+ if (argc >= 3 && argc & 1)
+ {
+ bool success = false;
+
+ uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success);
+
+ if (!success)
+ {
+ result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return result.Succeeded();
+ }
+
+ // shift off the index
+ command.Shift();
+ argc = command.GetArgumentCount();
+
+ for (uint32_t i=0; i<argc; i+=2, ++insert_idx)
+ {
+ const char *from = command.GetArgumentAtIndex(i);
+ const char *to = command.GetArgumentAtIndex(i+1);
+
+ if (from[0] && to[0])
+ {
+ bool last_pair = ((argc - i) == 2);
+ target->GetImageSearchPathList().Insert (ConstString(from),
+ ConstString(to),
+ insert_idx,
+ last_pair);
+ }
+ else
+ {
+ if (from[0])
+ result.AppendError ("<path-prefix> can't be empty");
+ else
+ result.AppendError ("<new-path-prefix> can't be empty");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("insert requires at least three arguments");
+ result.SetStatus (eReturnStatusFailed);
+ return result.Succeeded();
+ }
+
+ }
+ else
+ {
+ result.AppendError ("invalid target");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectTargetImageSearchPathsList : public CommandObject
+{
+public:
+
+ CommandObjectTargetImageSearchPathsList () :
+ CommandObject ("target image-search-paths list",
+ "Lists all current image search paths substitution pairs in the current target.",
+ "target image-search-paths list")
+ {
+ }
+
+ ~CommandObjectTargetImageSearchPathsList ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target * target = context->GetTarget();
+ if (target)
+ {
+ if (command.GetArgumentCount() != 0)
+ {
+ result.AppendError ("list takes no arguments");
+ result.SetStatus (eReturnStatusFailed);
+ return result.Succeeded();
+ }
+
+ target->GetImageSearchPathList().Dump(&result.GetOutputStream());
+ }
+ else
+ {
+ result.AppendError ("invalid target");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+class CommandObjectTargetImageSearchPathsQuery : public CommandObject
+{
+public:
+
+ CommandObjectTargetImageSearchPathsQuery () :
+ CommandObject ("target image-search-paths query",
+ "Transforms a path using the first applicable image search path.",
+ "target image-search-paths query <path>")
+ {
+ }
+
+ ~CommandObjectTargetImageSearchPathsQuery ()
+ {
+ }
+
+ bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Target * target = context->GetTarget();
+ if (target)
+ {
+ if (command.GetArgumentCount() != 1)
+ {
+ result.AppendError ("query requires one argument");
+ result.SetStatus (eReturnStatusFailed);
+ return result.Succeeded();
+ }
+
+ ConstString orig(command.GetArgumentAtIndex(0));
+ ConstString transformed;
+ if (target->GetImageSearchPathList().RemapPath(orig, transformed))
+ result.GetOutputStream().Printf("%s\n", transformed.GetCString());
+ else
+ result.GetOutputStream().Printf("%s\n", orig.GetCString());
+ }
+ else
+ {
+ result.AppendError ("invalid target");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+};
+
+// TODO: implement the target select later when we start doing multiple targets
+//#pragma mark CommandObjectTargetSelect
+//
+////-------------------------------------------------------------------------
+//// CommandObjectTargetSelect
+////-------------------------------------------------------------------------
+//
+//class CommandObjectTargetSelect : public CommandObject
+//{
+//public:
+//
+// CommandObjectTargetSelect () :
+// CommandObject ("frame select",
+// "Select the current frame by index in the current thread.",
+// "frame select <frame-index>")
+// {
+// }
+//
+// ~CommandObjectTargetSelect ()
+// {
+// }
+//
+// bool
+// Execute (Args& command,
+// CommandContext *context,
+// CommandInterpreter *interpreter,
+// CommandReturnObject &result)
+// {
+// ExecutionContext exe_ctx (context->GetExecutionContext());
+// if (exe_ctx.thread)
+// {
+// if (command.GetArgumentCount() == 1)
+// {
+// const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
+//
+// const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
+// const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
+// if (frame_idx < num_frames)
+// {
+// exe_ctx.thread->SetCurrentFrameByIndex (frame_idx);
+// exe_ctx.frame = exe_ctx.thread->GetCurrentFrame ().get();
+//
+// if (exe_ctx.frame)
+// {
+// if (DisplayFrameForExecutionContext (exe_ctx.thread,
+// exe_ctx.frame,
+// interpreter,
+// result.GetOutputStream(),
+// true,
+// true,
+// 3,
+// 3))
+// {
+// result.SetStatus (eReturnStatusSuccessFinishResult);
+// return result.Succeeded();
+// }
+// }
+// }
+// if (frame_idx == UINT32_MAX)
+// result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
+// else
+// result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
+// }
+// else
+// {
+// result.AppendError ("invalid arguments");
+// result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
+// }
+// }
+// else
+// {
+// result.AppendError ("no current thread");
+// }
+// result.SetStatus (eReturnStatusFailed);
+// return false;
+// }
+//};
+
+
+#pragma mark CommandObjectMultiwordTarget
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordImageSearchPaths
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordImageSearchPaths : public CommandObjectMultiword
+{
+public:
+
+ CommandObjectMultiwordImageSearchPaths (CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("target image-search-paths",
+ "A set of commands for operating on debugger target image search paths.",
+ "target image-search-paths <subcommand> [<subcommand-options>]")
+ {
+ LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsAdd ()), "add", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsClear ()), "clear", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsInsert ()), "insert", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsList ()), "list", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectTargetImageSearchPathsQuery ()), "query", interpreter);
+ }
+
+ ~CommandObjectMultiwordImageSearchPaths()
+ {
+ }
+};
+
+
+#pragma mark CommandObjectMultiwordTarget
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordTarget
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("target",
+ "A set of commands for operating on debugger targets.",
+ "target <subcommand> [<subcommand-options>]")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectMultiwordImageSearchPaths (interpreter)), "image-search-paths", interpreter);
+}
+
+CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget ()
+{
+}
+
diff --git a/lldb/source/Commands/CommandObjectTarget.h b/lldb/source/Commands/CommandObjectTarget.h
new file mode 100644
index 00000000000..cd569e1821d
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectTarget.h
@@ -0,0 +1,41 @@
+//===-- CommandObjectTarget.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectTarget_h_
+#define liblldb_CommandObjectTarget_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordTarget
+//-------------------------------------------------------------------------
+
+class CommandObjectMultiwordTarget : public CommandObjectMultiword
+{
+public:
+
+ CommandObjectMultiwordTarget (CommandInterpreter *interpreter);
+
+ virtual
+ ~CommandObjectMultiwordTarget ();
+
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectTarget_h_
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
new file mode 100644
index 00000000000..07777a19cfe
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -0,0 +1,1277 @@
+//===-- CommandObjectThread.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectThread.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/SourceManager.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanContinue.h"
+#include "lldb/Target/ThreadPlanStepInstruction.h"
+#include "lldb/Target/ThreadPlanStepOut.h"
+#include "lldb/Target/ThreadPlanStepRange.h"
+#include "lldb/Target/ThreadPlanStepInRange.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/LineEntry.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+bool
+lldb_private::DisplayThreadInfo
+(
+ CommandInterpreter *interpreter,
+ Stream &strm,
+ Thread *thread,
+ bool only_threads_with_stop_reason,
+ bool show_source
+)
+{
+ if (thread)
+ {
+ if (only_threads_with_stop_reason)
+ {
+ StopReason thread_stop_reason = eStopReasonNone;
+ Thread::StopInfo thread_stop_info;
+ if (thread->GetStopInfo(&thread_stop_info))
+ {
+ thread_stop_reason = thread_stop_info.GetStopReason();
+ if (thread_stop_reason == eStopReasonNone)
+ return false;
+ }
+ }
+
+ strm.Indent();
+ strm.Printf("%c ", thread->GetProcess().GetThreadList().GetCurrentThread().get() == thread ? '*' : ' ');
+
+ // Show one frame with only the first showing source
+ if (show_source)
+ {
+ DisplayFramesForExecutionContext (thread,
+ interpreter,
+ strm,
+ true,
+ 0, // Start at first frame
+ 1, // Number of frames to show
+ false,// Don't show the frame info since we already displayed most of it above...
+ 1, // Show source for the first frame
+ 3, // lines of source context before
+ 3); // lines of source context after
+ }
+ else
+ {
+ thread->DumpInfo (strm,
+ true, // Dump the stop reason?
+ true, // Dump the thread name?
+ true, // Dump the queue name?
+ 0); // Display context info for stack frame zero
+
+ strm.EOL();
+ }
+
+ return true;
+ }
+ return false;
+}
+
+size_t
+lldb_private::DisplayThreadsInfo
+(
+ CommandInterpreter *interpreter,
+ ExecutionContext *exe_ctx,
+ CommandReturnObject &result,
+ bool only_threads_with_stop_reason,
+ bool show_source
+)
+{
+ StreamString strm;
+
+ size_t num_thread_infos_dumped = 0;
+
+ if (!exe_ctx->process)
+ return 0;
+
+ const size_t num_threads = exe_ctx->process->GetThreadList().GetSize();
+ if (num_threads > 0)
+ {
+
+ for (uint32_t i = 0; i < num_threads; i++)
+ {
+ Thread *thread = exe_ctx->process->GetThreadList().GetThreadAtIndex(i).get();
+ if (thread)
+ {
+ if (DisplayThreadInfo (interpreter,
+ strm,
+ thread,
+ only_threads_with_stop_reason,
+ show_source))
+ ++num_thread_infos_dumped;
+ }
+ }
+ }
+
+ if (num_thread_infos_dumped > 0)
+ {
+ if (num_thread_infos_dumped < num_threads)
+ result.GetOutputStream().Printf("%u of %u threads stopped with reasons:\n", num_thread_infos_dumped, num_threads);
+
+ result.GetOutputStream().GetString().append(strm.GetString());
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ return num_thread_infos_dumped;
+}
+
+
+size_t
+lldb_private::DisplayFramesForExecutionContext
+(
+ Thread *thread,
+ CommandInterpreter *interpreter,
+ Stream& strm,
+ bool ascending,
+ uint32_t first_frame,
+ uint32_t num_frames,
+ bool show_frame_info,
+ uint32_t num_frames_with_source,
+ uint32_t source_lines_before,
+ uint32_t source_lines_after
+)
+{
+ if (thread == NULL)
+ return 0;
+
+ size_t num_frames_displayed = 0;
+
+ if (num_frames == 0)
+ return 0;
+
+ thread->DumpInfo (strm,
+ true, // Dump the stop reason?
+ true, // Dump the thread name?
+ true, // Dump the queue name?
+ 0); // Dump info for stack frame zero
+ strm.EOL();
+ strm.IndentMore();
+
+ StackFrameSP frame_sp;
+ int frame_idx = 0;
+
+ if (ascending)
+ {
+ for (frame_idx = first_frame; frame_idx < first_frame + num_frames; ++frame_idx)
+ {
+ frame_sp = thread->GetStackFrameAtIndex (frame_idx);
+ if (frame_sp.get() == NULL)
+ break;
+
+ if (DisplayFrameForExecutionContext (thread,
+ frame_sp.get(),
+ interpreter,
+ strm,
+ show_frame_info,
+ num_frames_with_source > first_frame - frame_idx,
+ source_lines_before,
+ source_lines_after) == false)
+ break;
+
+ ++num_frames_displayed;
+ }
+ }
+ else
+ {
+ for (frame_idx = first_frame + num_frames - 1; frame_idx >= first_frame; --frame_idx)
+ {
+ frame_sp = thread->GetStackFrameAtIndex (frame_idx);
+ if (frame_sp == NULL)
+ break;
+
+ if (DisplayFrameForExecutionContext (thread,
+ frame_sp.get(),
+ interpreter,
+ strm,
+ show_frame_info,
+ num_frames_with_source > first_frame - frame_idx,
+ source_lines_before,
+ source_lines_after) == false)
+ break;
+
+ ++num_frames_displayed;
+ }
+ }
+ strm.IndentLess();
+ return num_frames_displayed;
+}
+
+bool
+lldb_private::DisplayFrameForExecutionContext
+(
+ Thread *thread,
+ StackFrame *frame,
+ CommandInterpreter *interpreter,
+ Stream& strm,
+ bool show_frame_info,
+ bool show_source,
+ uint32_t source_lines_before,
+ uint32_t source_lines_after
+)
+{
+ // thread and frame must be filled in prior to calling this function
+ if (thread && frame)
+ {
+ if (show_frame_info)
+ {
+ strm.Indent();
+ frame->Dump (&strm, true);
+ strm.EOL();
+ }
+
+ SymbolContext sc (frame->GetSymbolContext(eSymbolContextCompUnit | eSymbolContextLineEntry));
+
+ if (show_source && sc.comp_unit && sc.line_entry.IsValid())
+ {
+ interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbers (
+ sc.line_entry.file,
+ sc.line_entry.line,
+ 3,
+ 3,
+ "->",
+ &strm);
+
+ }
+ return true;
+ }
+ return false;
+}
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadBacktrace
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadBacktrace : public CommandObject
+{
+public:
+
+ CommandObjectThreadBacktrace () :
+ CommandObject ("thread backtrace",
+ "Shows the stack for one or more threads.",
+ "thread backtrace [<thread-idx>] ...",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
+ m_ascending (true)
+ {
+ }
+
+ ~CommandObjectThreadBacktrace()
+ {
+ }
+
+
+ bool
+ Execute
+ (
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+ )
+ {
+ if (command.GetArgumentCount() == 0)
+ {
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (exe_ctx.thread)
+ {
+ bool show_frame_info = true;
+ uint32_t num_frames_with_source = 0; // Don't show any frasmes with source when backtracing
+ if (DisplayFramesForExecutionContext (exe_ctx.thread,
+ interpreter,
+ result.GetOutputStream(),
+ m_ascending,
+ 0,
+ UINT32_MAX,
+ show_frame_info,
+ num_frames_with_source,
+ 3,
+ 3))
+ {
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ }
+ else
+ {
+ result.AppendError ("invalid thread");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("backtrace doesn't take arguments (for now)");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+ }
+protected:
+ bool m_ascending;
+};
+
+
+typedef enum StepScope
+{
+ eStepScopeSource,
+ eStepScopeInstruction
+};
+
+class CommandObjectThreadStepWithTypeAndScope : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options()
+ {
+ // Keep default values of all options in one place: ResetOptionValues ()
+ ResetOptionValues ();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 'a':
+ {
+ bool success;
+ m_avoid_no_debug = Args::StringToBoolean (option_arg, true, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("Invalid boolean value for option '%c'.\n", short_option);
+ }
+ break;
+ case 'm':
+ {
+ bool found_one = false;
+ OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
+ m_run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
+ if (!found_one)
+ error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+
+ }
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ m_avoid_no_debug = true;
+ m_run_mode = eOnlyDuringStepping;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ bool m_avoid_no_debug;
+ RunMode m_run_mode;
+ };
+
+ CommandObjectThreadStepWithTypeAndScope (const char *name,
+ const char *help,
+ const char *syntax,
+ uint32_t flags,
+ StepType step_type,
+ StepScope step_scope) :
+ CommandObject (name, help, syntax, flags),
+ m_step_type (step_type),
+ m_step_scope (step_scope),
+ m_options ()
+ {
+ }
+
+ virtual
+ ~CommandObjectThreadStepWithTypeAndScope ()
+ {
+ }
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ bool synchronous_execution = interpreter->GetSynchronous();
+
+ if (process == NULL)
+ {
+ result.AppendError ("need a valid process to step");
+ result.SetStatus (eReturnStatusFailed);
+
+ }
+ else
+ {
+ const uint32_t num_threads = process->GetThreadList().GetSize();
+ Thread *thread = NULL;
+
+ if (command.GetArgumentCount() == 0)
+ {
+ thread = process->GetThreadList().GetCurrentThread().get();
+ if (thread == NULL)
+ {
+ result.AppendError ("no current thread in process");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
+ uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
+ if (step_thread_idx == LLDB_INVALID_INDEX32)
+ {
+ result.AppendErrorWithFormat ("Invalid thread index '%s'.\n", thread_idx_cstr);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
+ if (thread == NULL)
+ {
+ result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
+ step_thread_idx, 0, num_threads);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+
+ const bool abort_other_plans = false;
+ const lldb::RunMode stop_other_threads = m_options.m_run_mode;
+
+ // This is a bit unfortunate, but not all the commands in this command object support
+ // only while stepping, so I use the bool for them.
+ bool bool_stop_other_threads;
+ if (m_options.m_run_mode == eAllThreads)
+ bool_stop_other_threads = false;
+ else
+ bool_stop_other_threads = true;
+
+ if (m_step_type == eStepTypeInto)
+ {
+ StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
+ ThreadPlan *new_plan;
+
+ if (frame->HasDebugInformation ())
+ {
+ new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans, m_step_type,
+ frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
+ frame->GetSymbolContext(eSymbolContextEverything),
+ stop_other_threads);
+ if (new_plan)
+ {
+ ThreadPlanStepInRange *real_plan = dynamic_cast<ThreadPlanStepInRange *> (new_plan);
+ if (real_plan)
+ {
+ if (m_options.m_avoid_no_debug)
+ {
+ real_plan->GetFlags().Set (ThreadPlanShouldStopHere::eAvoidNoDebug);
+ }
+ else
+ {
+ real_plan->GetFlags().Clear (ThreadPlanShouldStopHere::eAvoidNoDebug);
+ }
+ }
+ }
+ }
+ else
+ new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
+
+ process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+ process->Resume ();
+ }
+ else if (m_step_type == eStepTypeOver)
+ {
+ StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
+ ThreadPlan *new_plan;
+
+ if (frame->HasDebugInformation())
+ new_plan = thread->QueueThreadPlanForStepRange (abort_other_plans,
+ m_step_type,
+ frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
+ frame->GetSymbolContext(eSymbolContextEverything),
+ stop_other_threads);
+ else
+ new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
+ abort_other_plans,
+ bool_stop_other_threads);
+
+ // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
+ // Maybe there should be a parameter to control this.
+ new_plan->SetOkayToDiscard(false);
+
+ process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+ process->Resume ();
+ }
+ else if (m_step_type == eStepTypeTrace)
+ {
+ thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
+ process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+ process->Resume ();
+ }
+ else if (m_step_type == eStepTypeTraceOver)
+ {
+ thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
+ process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+ process->Resume ();
+ }
+ else if (m_step_type == eStepTypeOut)
+ {
+ ThreadPlan *new_plan;
+
+ new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, bool_stop_other_threads, eVoteYes, eVoteNoOpinion);
+ // FIXME: This will keep the step plan on the thread stack when we hit a breakpoint while stepping over.
+ // Maybe there should be a parameter to control this.
+ new_plan->SetOkayToDiscard(false);
+
+ process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+ process->Resume ();
+ }
+ else
+ {
+ result.AppendError ("step type is not supported");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ if (synchronous_execution)
+ {
+ StateType state = process->WaitForProcessToStop (NULL);
+
+ //EventSP event_sp;
+ //StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
+ //while (! StateIsStoppedState (state))
+ // {
+ // state = process->WaitForStateChangedEvents (NULL, event_sp);
+ // }
+ process->GetThreadList().SetCurrentThreadByID (thread->GetID());
+ result.SetDidChangeProcessState (true);
+ result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ return result.Succeeded();
+ }
+
+protected:
+ StepType m_step_type;
+ StepScope m_step_scope;
+ CommandOptions m_options;
+};
+
+static lldb::OptionEnumValueElement
+g_tri_running_mode[] =
+{
+{ eOnlyThisThread, "thisThread", "Run only this thread"},
+{ eAllThreads, "allThreads", "Run all threads"},
+{ eOnlyDuringStepping, "whileStepping", "Run only this thread while stepping"},
+{ 0, NULL, NULL }
+};
+
+static lldb::OptionEnumValueElement
+g_duo_running_mode[] =
+{
+{ eOnlyThisThread, "thisThread", "Run only this thread"},
+{ eAllThreads, "allThreads", "Run all threads"},
+{ 0, NULL, NULL }
+};
+
+lldb::OptionDefinition
+CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] =
+{
+{ 0, true, "avoid_no_debug", 'a', required_argument, NULL, 0, "<avoid_no_debug>", "Should step-in step over functions with no debug information"},
+{ 0, true, "run_mode", 'm', required_argument, g_tri_running_mode, 0, "<run_mode>", "Determine how to run other threads while stepping this one"},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadContinue
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadContinue : public CommandObject
+{
+public:
+
+ CommandObjectThreadContinue () :
+ CommandObject ("thread continue",
+ "Continues execution of one or more threads in an active process.",
+ "thread continue <thread-index> [<thread-index> ...]",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+ {
+ }
+
+
+ virtual
+ ~CommandObjectThreadContinue ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ bool synchronous_execution = interpreter->GetSynchronous ();
+
+ if (!context->GetTarget())
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError ("no process exists. Cannot continue");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ StateType state = process->GetState();
+ if ((state == eStateCrashed) || (state == eStateStopped) || (state == eStateSuspended))
+ {
+ const uint32_t num_threads = process->GetThreadList().GetSize();
+ uint32_t idx;
+ const size_t argc = command.GetArgumentCount();
+ if (argc > 0)
+ {
+ std::vector<uint32_t> resume_thread_indexes;
+ for (uint32_t i=0; i<argc; ++i)
+ {
+ idx = Args::StringToUInt32 (command.GetArgumentAtIndex(0), LLDB_INVALID_INDEX32);
+ if (idx < num_threads)
+ resume_thread_indexes.push_back(idx);
+ else
+ result.AppendWarningWithFormat("Thread index %u out of range.\n", idx);
+ }
+
+ if (resume_thread_indexes.empty())
+ {
+ result.AppendError ("no valid thread indexes were specified");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ result.AppendMessage ("Resuming thread ");
+ for (idx=0; idx<num_threads; ++idx)
+ {
+ Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
+ if (find(resume_thread_indexes.begin(), resume_thread_indexes.end(), idx) != resume_thread_indexes.end())
+ {
+ result.AppendMessageWithFormat ("%u ", idx);
+ thread->SetResumeState (eStateRunning);
+ }
+ else
+ {
+ thread->SetResumeState (eStateSuspended);
+ }
+ }
+ result.AppendMessageWithFormat ("in process %i\n", process->GetID());
+ }
+ }
+ else
+ {
+ Thread *current_thread = process->GetThreadList().GetCurrentThread().get();
+ if (current_thread == NULL)
+ {
+ result.AppendError ("the process doesn't have a current thread");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ // Set the actions that the threads should each take when resuming
+ for (idx=0; idx<num_threads; ++idx)
+ {
+ Thread *thread = process->GetThreadList().GetThreadAtIndex(idx).get();
+ if (thread == current_thread)
+ {
+ result.AppendMessageWithFormat ("Resuming thread 0x%4.4x in process %i\n", thread->GetID(), process->GetID());
+ thread->SetResumeState (eStateRunning);
+ }
+ else
+ {
+ thread->SetResumeState (eStateSuspended);
+ }
+ }
+ }
+
+ Error error (process->Resume());
+ if (error.Success())
+ {
+ result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
+ if (synchronous_execution)
+ {
+ StateType state = process->WaitForProcessToStop (NULL);
+
+ result.SetDidChangeProcessState (true);
+ result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Failed to resume process: %s\n", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
+ StateAsCString(state));
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return result.Succeeded();
+ }
+
+};
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadUntil
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadUntil : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+ uint32_t m_thread_idx;
+ uint32_t m_frame_idx;
+
+ CommandOptions () :
+ Options(),
+ m_thread_idx(LLDB_INVALID_THREAD_ID),
+ m_frame_idx(LLDB_INVALID_FRAME_ID)
+ {
+ // Keep default values of all options in one place: ResetOptionValues ()
+ ResetOptionValues ();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 't':
+ {
+ uint32_t m_thread_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_INDEX32);
+ if (m_thread_idx == LLDB_INVALID_INDEX32)
+ {
+ error.SetErrorStringWithFormat ("Invalid thread index '%s'.\n", option_arg);
+ }
+ }
+ break;
+ case 'f':
+ {
+ m_frame_idx = Args::StringToUInt32 (option_arg, LLDB_INVALID_FRAME_ID);
+ if (m_frame_idx == LLDB_INVALID_FRAME_ID)
+ {
+ error.SetErrorStringWithFormat ("Invalid frame index '%s'.\n", option_arg);
+ }
+ }
+ break;
+ case 'm':
+ {
+ bool found_one = false;
+ OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values;
+ lldb::RunMode run_mode = (lldb::RunMode) Args::StringToOptionEnum(option_arg, enum_values, eOnlyDuringStepping, &found_one);
+
+ if (!found_one)
+ error.SetErrorStringWithFormat("Invalid enumeration value for option '%c'.\n", short_option);
+ else if (run_mode == eAllThreads)
+ m_stop_others = false;
+ else
+ m_stop_others = true;
+
+ }
+ break;
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+
+ }
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+ m_thread_idx = LLDB_INVALID_THREAD_ID;
+ m_frame_idx = 0;
+ m_stop_others = false;
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ uint32_t m_step_thread_idx;
+ bool m_stop_others;
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+ };
+
+ CommandObjectThreadUntil () :
+ CommandObject ("thread until",
+ "Runs the current or specified thread until it reaches a given line number or leaves the current function.",
+ "thread until [<cmd-options>] <line-number>",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
+ m_options ()
+ {
+ }
+
+
+ virtual
+ ~CommandObjectThreadUntil ()
+ {
+ }
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ bool synchronous_execution = interpreter->GetSynchronous ();
+
+ if (!context->GetTarget())
+ {
+ result.AppendError ("invalid target, set executable file using 'file' command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError ("need a valid process to step");
+ result.SetStatus (eReturnStatusFailed);
+
+ }
+ else
+ {
+ Thread *thread = NULL;
+ uint32_t line_number;
+
+ if (command.GetArgumentCount() != 1)
+ {
+ result.AppendErrorWithFormat ("No line number provided:\n%s", GetSyntax());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ line_number = Args::StringToUInt32 (command.GetArgumentAtIndex(0), UINT32_MAX);
+ if (line_number == UINT32_MAX)
+ {
+ result.AppendErrorWithFormat ("Invalid line number: '%s'.\n", command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (m_options.m_thread_idx == LLDB_INVALID_THREAD_ID)
+ {
+ thread = process->GetThreadList().GetCurrentThread().get();
+ }
+ else
+ {
+ thread = process->GetThreadList().GetThreadAtIndex(m_options.m_thread_idx).get();
+ }
+
+ if (thread == NULL)
+ {
+ const uint32_t num_threads = process->GetThreadList().GetSize();
+ result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n", m_options.m_thread_idx, 0, num_threads);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ const bool abort_other_plans = true;
+
+ StackFrame *frame = thread->GetStackFrameAtIndex(m_options.m_frame_idx).get();
+ if (frame == NULL)
+ {
+
+ result.AppendErrorWithFormat ("Frame index %u is out of range for thread %u.\n", m_options.m_frame_idx, m_options.m_thread_idx);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ ThreadPlan *new_plan;
+
+ if (frame->HasDebugInformation ())
+ {
+ // Finally we got here... Translate the given line number to a bunch of addresses:
+ SymbolContext sc(frame->GetSymbolContext (eSymbolContextCompUnit));
+ LineTable *line_table = NULL;
+ if (sc.comp_unit)
+ line_table = sc.comp_unit->GetLineTable();
+
+ if (line_table == NULL)
+ {
+ result.AppendErrorWithFormat ("Failed to resolve the line table for frame %u of thread index %u.\n",
+ m_options.m_frame_idx, m_options.m_thread_idx);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ LineEntry function_start;
+ uint32_t index_ptr = 0, end_ptr;
+ std::vector<addr_t> address_list;
+
+ // Find the beginning & end index of the
+ AddressRange fun_addr_range = sc.function->GetAddressRange();
+ Address fun_start_addr = fun_addr_range.GetBaseAddress();
+ line_table->FindLineEntryByAddress (fun_start_addr, function_start, &index_ptr);
+
+ Address fun_end_addr(fun_start_addr.GetSection(), fun_start_addr.GetOffset() + fun_addr_range.GetByteSize());
+ line_table->FindLineEntryByAddress (fun_end_addr, function_start, &end_ptr);
+
+ while (index_ptr <= end_ptr)
+ {
+ LineEntry line_entry;
+ index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry);
+ if (index_ptr == UINT32_MAX)
+ break;
+
+ addr_t address = line_entry.range.GetBaseAddress().GetLoadAddress(process);
+ if (address != LLDB_INVALID_ADDRESS)
+ address_list.push_back (address);
+ index_ptr++;
+ }
+
+ new_plan = thread->QueueThreadPlanForStepUntil (abort_other_plans, address_list.data(), address_list.size(), m_options.m_stop_others);
+ new_plan->SetOkayToDiscard(false);
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("Frame index %u of thread %u has no debug information.\n", m_options.m_frame_idx, m_options.m_thread_idx);
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+
+ }
+
+ process->GetThreadList().SetCurrentThreadByID (m_options.m_thread_idx);
+ Error error (process->Resume ());
+ if (error.Success())
+ {
+ result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
+ if (synchronous_execution)
+ {
+ StateType state = process->WaitForProcessToStop (NULL);
+
+ result.SetDidChangeProcessState (true);
+ result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ else
+ {
+ result.SetStatus (eReturnStatusSuccessContinuingNoResult);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ }
+ return result.Succeeded();
+ }
+protected:
+ CommandOptions m_options;
+
+};
+
+lldb::OptionDefinition
+CommandObjectThreadUntil::CommandOptions::g_option_table[] =
+{
+{ 0, true, "frame", 'f', required_argument, NULL, 0, "<frame>", "Frame index for until operation - defaults to 0"},
+{ 0, true, "thread", 't', required_argument, NULL, 0, "<thread>", "Thread index for the thread for until operation"},
+{ 0, true, "run_mode", 'm', required_argument, g_duo_running_mode, 0, "<run_mode>", "Determine how to run other threads while stepping this one"},
+{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadSelect
+//-------------------------------------------------------------------------
+
+class CommandObjectThreadSelect : public CommandObject
+{
+public:
+
+ CommandObjectThreadSelect () :
+ CommandObject ("thread select",
+ "Selects a threads as the currently active thread.",
+ "thread select <thread-index>",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+ {
+ }
+
+
+ virtual
+ ~CommandObjectThreadSelect ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ Process *process = context->GetExecutionContext().process;
+ if (process == NULL)
+ {
+ result.AppendError ("no process");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else if (command.GetArgumentCount() != 1)
+ {
+ result.AppendErrorWithFormat("'%s' takes exactly one thread index argument:\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ uint32_t index_id = Args::StringToUInt32(command.GetArgumentAtIndex(0), 0, 0);
+
+ Thread *new_thread = process->GetThreadList().FindThreadByIndexID(index_id).get();
+ if (new_thread == NULL)
+ {
+ result.AppendErrorWithFormat ("Invalid thread #%s.\n", command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ process->GetThreadList().SetCurrentThreadByID(new_thread->GetID());
+
+ DisplayThreadInfo (interpreter,
+ result.GetOutputStream(),
+ new_thread,
+ false,
+ true);
+
+ return result.Succeeded();
+ }
+
+};
+
+
+//-------------------------------------------------------------------------
+// CommandObjectThreadList
+//-------------------------------------------------------------------------
+
+CommandObjectThreadList::CommandObjectThreadList ():
+ CommandObject ("thread list",
+ "Shows a summary of all current threads in a process.",
+ "thread list",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+{
+}
+
+CommandObjectThreadList::~CommandObjectThreadList()
+{
+}
+
+bool
+CommandObjectThreadList::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ StreamString &strm = result.GetOutputStream();
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (exe_ctx.process)
+ {
+ const StateType state = exe_ctx.process->GetState();
+
+ if (StateIsStoppedState(state))
+ {
+ if (state == eStateExited)
+ {
+ int exit_status = exe_ctx.process->GetExitStatus();
+ const char *exit_description = exe_ctx.process->GetExitDescription();
+ strm.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
+ exe_ctx.process->GetID(),
+ exit_status,
+ exit_status,
+ exit_description ? exit_description : "");
+ }
+ else
+ {
+ strm.Printf ("Process %d state is %s\n", exe_ctx.process->GetID(), StateAsCString (state));
+ if (exe_ctx.thread == NULL)
+ exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
+ if (exe_ctx.thread != NULL)
+ {
+ DisplayThreadsInfo (interpreter, &exe_ctx, result, false, false);
+ }
+ else
+ {
+ result.AppendError ("no valid thread found in current process");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ }
+ else
+ {
+ result.AppendError ("process is currently running");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("no current location or status available");
+ result.SetStatus (eReturnStatusFailed);
+ }
+ return result.Succeeded();
+}
+
+//-------------------------------------------------------------------------
+// CommandObjectMultiwordThread
+//-------------------------------------------------------------------------
+
+CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("thread",
+ "A set of commands for operating on one or more thread within a running process.",
+ "thread <subcommand> [<subcommand-options>]")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadBacktrace ()), "backtrace", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadContinue ()), "continue", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadList ()), "list", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadSelect ()), "select", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadUntil ()), "until", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-in",
+ "Source level single step in in specified thread (current thread, if none specified).",
+ "thread step-in [<thread-id>]",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+ eStepTypeInto,
+ eStepScopeSource)),
+ "step-in", interpreter);
+
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-out",
+ "Source level single step out in specified thread (current thread, if none specified).",
+ "thread step-out [<thread-id>]",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+ eStepTypeOut,
+ eStepScopeSource)),
+ "step-out", interpreter);
+
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-over",
+ "Source level single step over in specified thread (current thread, if none specified).",
+ "thread step-over [<thread-id>]",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+ eStepTypeOver,
+ eStepScopeSource)),
+ "step-over", interpreter);
+
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst",
+ "Single step one instruction in specified thread (current thread, if none specified).",
+ "thread step-inst [<thread-id>]",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+ eStepTypeTrace,
+ eStepScopeInstruction)),
+ "step-inst", interpreter);
+ LoadSubCommand (CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope ("thread step-inst-over",
+ "Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
+ "thread step-inst-over [<thread-id>]",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
+ eStepTypeTraceOver,
+ eStepScopeInstruction)),
+ "step-inst-over", interpreter);
+}
+
+CommandObjectMultiwordThread::~CommandObjectMultiwordThread ()
+{
+}
+
+
diff --git a/lldb/source/Commands/CommandObjectThread.h b/lldb/source/Commands/CommandObjectThread.h
new file mode 100644
index 00000000000..21bba714626
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectThread.h
@@ -0,0 +1,87 @@
+//===-- CommandObjectThread.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectThread_h_
+#define liblldb_CommandObjectThread_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+class CommandObjectThreadList : public CommandObject
+{
+public:
+
+ CommandObjectThreadList ();
+
+ ~CommandObjectThreadList ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+};
+
+
+class CommandObjectMultiwordThread : public CommandObjectMultiword
+{
+public:
+
+ CommandObjectMultiwordThread (CommandInterpreter *interpreter);
+
+ virtual
+ ~CommandObjectMultiwordThread ();
+
+};
+
+
+bool
+DisplayThreadInfo (CommandInterpreter *interpreter,
+ Stream &strm,
+ Thread *thread,
+ bool only_threads_with_stop_reason,
+ bool show_source);
+
+size_t
+DisplayThreadsInfo (CommandInterpreter *interpreter,
+ ExecutionContext *exe_ctx,
+ CommandReturnObject &result,
+ bool only_threads_with_stop_reason,
+ bool show_source);
+
+size_t
+DisplayFramesForExecutionContext (Thread *thread,
+ CommandInterpreter *interpreter,
+ Stream& strm,
+ bool ascending,
+ uint32_t first_frame,
+ uint32_t num_frames,
+ bool show_frame_info,
+ uint32_t num_frames_with_source,
+ uint32_t source_lines_before,
+ uint32_t source_lines_after);
+
+bool
+DisplayFrameForExecutionContext (Thread *thread,
+ StackFrame *frame,
+ CommandInterpreter *interpreter,
+ Stream& strm,
+ bool show_frame_info,
+ bool show_source,
+ uint32_t source_lines_before,
+ uint32_t source_lines_after);
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectThread_h_
diff --git a/lldb/source/Commands/CommandObjectTranslate.cpp b/lldb/source/Commands/CommandObjectTranslate.cpp
new file mode 100644
index 00000000000..48a10626c8d
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectTranslate.cpp
@@ -0,0 +1,75 @@
+//===-- CommandObjectTranslate.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectTranslate.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Args.h"
+#include "lldb/Core/Options.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectTranslate
+//-------------------------------------------------------------------------
+
+CommandObjectTranslate::CommandObjectTranslate () :
+ CommandObject ("translate",
+ "Shows the actual function called for a given debugger command.",
+ "translate <command>")
+{
+}
+
+CommandObjectTranslate::~CommandObjectTranslate()
+{
+}
+
+
+bool
+CommandObjectTranslate::Execute
+(
+ Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result
+)
+{
+ CommandObject *cmd_obj;
+
+ if (command.GetArgumentCount() != 0)
+ {
+ cmd_obj = interpreter->GetCommandObject(command.GetArgumentAtIndex(0));
+ if (cmd_obj)
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ result.AppendMessageWithFormat ("%s\n", cmd_obj->Translate());
+ }
+ else
+ {
+ result.AppendErrroWithFormat
+ ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+ command.GetArgumentAtIndex(0));
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("must call translate with a valid command");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return result.Succeeded();
+}
diff --git a/lldb/source/Commands/CommandObjectTranslate.h b/lldb/source/Commands/CommandObjectTranslate.h
new file mode 100644
index 00000000000..efc3c8b4092
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectTranslate.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectTranslate.h --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectTranslate_h_
+#define liblldb_CommandObjectTranslate_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectTranslate
+//-------------------------------------------------------------------------
+
+class CommandObjectTranslate : public CommandObject
+{
+public:
+
+ CommandObjectTranslate ();
+
+ virtual
+ ~CommandObjectTranslate ();
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectTranslate_h_
diff --git a/lldb/source/Commands/CommandObjectUnalias.cpp b/lldb/source/Commands/CommandObjectUnalias.cpp
new file mode 100644
index 00000000000..6c2f5085cf8
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectUnalias.cpp
@@ -0,0 +1,87 @@
+//===-- CommandObjectUnalias.cpp --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectUnalias.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//-------------------------------------------------------------------------
+// CommandObjectUnalias
+//-------------------------------------------------------------------------
+
+CommandObjectUnalias::CommandObjectUnalias () :
+ CommandObject ("unalias",
+ "Allows the user to remove/delete a user-defined command abbreviation.",
+ "unalias <alias-name-to-be-removed>")
+{
+}
+
+CommandObjectUnalias::~CommandObjectUnalias()
+{
+}
+
+
+bool
+CommandObjectUnalias::Execute (Args& args, CommandContext *context, CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+{
+ CommandObject::CommandMap::iterator pos;
+ CommandObject *cmd_obj;
+
+ if (args.GetArgumentCount() != 0)
+ {
+ const char *command_name = args.GetArgumentAtIndex(0);
+ cmd_obj = interpreter->GetCommandObject(command_name);
+ if (cmd_obj)
+ {
+ if (interpreter->CommandExists (command_name))
+ {
+ result.AppendErrorWithFormat ("'%s' is a permanent debugger command and cannot be removed.\n",
+ command_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+
+ if (interpreter->RemoveAlias (command_name) == false)
+ {
+ if (interpreter->AliasExists (command_name))
+ result.AppendErrorWithFormat ("Error occurred while attempting to unalias '%s'.\n", command_name);
+ else
+ result.AppendErrorWithFormat ("'%s' is not an existing alias.\n", command_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ }
+ }
+ else
+ {
+ result.AppendErrorWithFormat ("'%s' is not a known command.\nTry 'help' to see a current list of commands.\n",
+ command_name);
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+ else
+ {
+ result.AppendError ("must call 'unalias' with a valid alias");
+ result.SetStatus (eReturnStatusFailed);
+ }
+
+ return result.Succeeded();
+}
+
diff --git a/lldb/source/Commands/CommandObjectUnalias.h b/lldb/source/Commands/CommandObjectUnalias.h
new file mode 100644
index 00000000000..5d1cafbcc71
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectUnalias.h
@@ -0,0 +1,44 @@
+//===-- CommandObjectUnalias.h ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectUnalias_h_
+#define liblldb_CommandObjectUnalias_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObject.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectUnalias
+//-------------------------------------------------------------------------
+
+class CommandObjectUnalias : public CommandObject
+{
+public:
+
+ CommandObjectUnalias ();
+
+ virtual
+ ~CommandObjectUnalias ();
+
+ virtual bool
+ Execute (Args& args,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectUnalias_h_
diff --git a/lldb/source/Commands/CommandObjectVariable.cpp b/lldb/source/Commands/CommandObjectVariable.cpp
new file mode 100644
index 00000000000..6bde4829be0
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectVariable.cpp
@@ -0,0 +1,801 @@
+//===-- CommandObjectVariable.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CommandObjectVariable.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Options.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectVariable.h"
+
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Symbol/VariableList.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//void
+//DumpValueObjectValues (Stream *sout, const char *root_valobj_name, ValueObjectSP& valobj_sp, bool follow_ptrs_and_refs, uint32_t curr_depth, uint32_t max_depth)
+//{
+// ValueObject *valobj = valobj_sp.get();
+// if (valobj)
+// {
+// const char *name_cstr = valobj->GetName().AsCString(NULL);
+// const char *val_cstr = valobj->GetValueAsCString();
+// const char *loc_cstr = valobj->GetLocationAsCString();
+// const char *type_cstr = valobj->GetTypeName().AsCString();
+// const char *sum_cstr = valobj->GetSummaryAsCString();
+// const char *err_cstr = valobj->GetError().AsCString();
+// // Indent
+// sout->Indent();
+// if (root_valobj_name)
+// {
+// sout->Printf ("%s = ", root_valobj_name);
+// }
+//
+// if (name_cstr)
+// sout->Printf ("%s => ", name_cstr);
+//
+// sout->Printf ("ValueObject{%u}", valobj->GetID());
+// const uint32_t num_children = valobj->GetNumChildren();
+//
+// if (type_cstr)
+// sout->Printf (", type = '%s'", type_cstr);
+//
+// if (loc_cstr)
+// sout->Printf (", location = %s", loc_cstr);
+//
+// sout->Printf (", num_children = %u", num_children);
+//
+// if (val_cstr)
+// sout->Printf (", value = %s", val_cstr);
+//
+// if (err_cstr)
+// sout->Printf (", error = %s", err_cstr);
+//
+// if (sum_cstr)
+// sout->Printf (", summary = %s", sum_cstr);
+//
+// sout->EOL();
+// bool is_ptr_or_ref = ClangASTContext::IsPointerOrReferenceType (valobj->GetOpaqueClangQualType());
+// if (!follow_ptrs_and_refs && is_ptr_or_ref)
+// return;
+//
+// if (curr_depth < max_depth)
+// {
+// for (uint32_t idx=0; idx<num_children; ++idx)
+// {
+// ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
+// if (child_sp.get())
+// {
+// sout->IndentMore();
+// DumpValueObjectValues (sout, NULL, child_sp, follow_ptrs_and_refs, curr_depth + 1, max_depth);
+// sout->IndentLess();
+// }
+// }
+// }
+// }
+//}
+
+//----------------------------------------------------------------------
+// List images with associated information
+//----------------------------------------------------------------------
+class CommandObjectVariableList : public CommandObject
+{
+public:
+
+ class CommandOptions : public Options
+ {
+ public:
+
+ CommandOptions () :
+ Options()
+ {
+ ResetOptionValues ();
+ }
+
+ virtual
+ ~CommandOptions ()
+ {
+ }
+
+ virtual Error
+ SetOptionValue (int option_idx, const char *option_arg)
+ {
+ Error error;
+ bool success;
+ char short_option = (char) m_getopt_table[option_idx].val;
+ switch (short_option)
+ {
+ case 'o': use_objc = true; break;
+ case 'n': name = option_arg; break;
+ case 'r': use_regex = true; break;
+ case 'a': show_args = false; break;
+ case 'l': show_locals = false; break;
+ case 'g': show_globals = false; break;
+ case 't': show_types = false; break;
+ case 'y': show_summary = false; break;
+ case 'L': show_location= true; break;
+ case 'D': debug = true; break;
+ case 'd':
+ max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("Invalid max depth '%s'.\n", option_arg);
+ break;
+
+ case 'p':
+ ptr_depth = Args::StringToUInt32 (option_arg, 0, 0, &success);
+ if (!success)
+ error.SetErrorStringWithFormat("Invalid pointer depth '%s'.\n", option_arg);
+ break;
+
+ case 'G':
+ {
+ ConstString const_string (option_arg);
+ globals.push_back(const_string);
+ }
+ break;
+
+ case 's':
+ show_scope = true;
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ void
+ ResetOptionValues ()
+ {
+ Options::ResetOptionValues();
+
+ name.clear();
+ use_objc = false;
+ use_regex = false;
+ show_args = true;
+ show_locals = true;
+ show_globals = true;
+ show_types = true;
+ show_scope = false;
+ show_summary = true;
+ show_location = false;
+ debug = false;
+ max_depth = UINT32_MAX;
+ ptr_depth = 0;
+ globals.clear();
+ }
+
+ const lldb::OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static lldb::OptionDefinition g_option_table[];
+ std::string name;
+ bool use_objc;
+ bool use_regex;
+ bool show_args;
+ bool show_locals;
+ bool show_globals;
+ bool show_types;
+ bool show_scope; // local/arg/global/static
+ bool show_summary;
+ bool show_location;
+ bool debug;
+ uint32_t max_depth; // The depth to print when dumping concrete (not pointers) aggreate values
+ uint32_t ptr_depth; // The default depth that is dumped when we find pointers
+ std::vector<ConstString> globals;
+ // Instance variables to hold the values for command options.
+ };
+
+ CommandObjectVariableList () :
+ CommandObject (
+ "variable list",
+ "Show specified argument, local variable, static variable or global variable. If none specified, list them all.",
+ "variable list [<cmd-options>] [<var-name1> [<var-name2>...]]")
+ {
+ }
+
+ virtual
+ ~CommandObjectVariableList ()
+ {
+ }
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+ void
+ DumpVariable (CommandReturnObject &result, ExecutionContext *exe_ctx, Variable *variable)
+ {
+ if (variable)
+ {
+ Stream &s = result.GetOutputStream();
+ DWARFExpression &expr = variable->LocationExpression();
+ Value expr_result;
+ Error expr_error;
+ Type *variable_type = variable->GetType();
+ bool expr_success = expr.Evaluate(exe_ctx, NULL, NULL, expr_result, &expr_error);
+
+ if (m_options.debug)
+ s.Printf ("Variable{0x%8.8x}: ", variable->GetID());
+
+ if (!expr_success)
+ s.Printf ("%s = ERROR (%s)", variable->GetName().AsCString(NULL), expr_error.AsCString());
+ else
+ {
+ Value::ValueType expr_value_type = expr_result.GetValueType();
+ switch (expr_value_type)
+ {
+ case Value::eValueTypeScalar:
+ s.Printf ("%s = ", variable->GetName().AsCString(NULL));
+ if (variable_type)
+ {
+ DataExtractor data;
+ if (expr_result.ResolveValue (exe_ctx, NULL).GetData (data))
+ variable_type->DumpValue (exe_ctx, &s, data, 0, m_options.show_types, m_options.show_summary, m_options.debug);
+ }
+ break;
+
+ case Value::eValueTypeFileAddress:
+ case Value::eValueTypeLoadAddress:
+ case Value::eValueTypeHostAddress:
+ {
+ s.Printf ("%s = ", variable->GetName().AsCString(NULL));
+ lldb::addr_t addr = LLDB_INVALID_ADDRESS;
+ lldb::AddressType addr_type = eAddressTypeLoad;
+
+ if (expr_value_type == Value::eValueTypeFileAddress)
+ {
+ lldb::addr_t file_addr = expr_result.ResolveValue (exe_ctx, NULL).ULongLong(LLDB_INVALID_ADDRESS);
+ SymbolContext var_sc;
+ variable->CalculateSymbolContext(&var_sc);
+ if (var_sc.module_sp)
+ {
+ ObjectFile *objfile = var_sc.module_sp->GetObjectFile();
+ if (objfile)
+ {
+ Address so_addr(file_addr, objfile->GetSectionList());
+ addr = so_addr.GetLoadAddress(exe_ctx->process);
+ }
+ if (addr == LLDB_INVALID_ADDRESS)
+ {
+ result.GetErrorStream().Printf ("error: %s is not loaded", var_sc.module_sp->GetFileSpec().GetFilename().AsCString());
+ }
+ }
+ else
+ {
+ result.GetErrorStream().Printf ("error: unable to resolve the variable address 0x%llx", file_addr);
+ }
+ }
+ else
+ {
+ if (expr_value_type == Value::eValueTypeHostAddress)
+ addr_type = eAddressTypeHost;
+ addr = expr_result.ResolveValue (exe_ctx, NULL).ULongLong(LLDB_INVALID_ADDRESS);
+ }
+
+ if (addr != LLDB_INVALID_ADDRESS)
+ {
+ if (m_options.debug)
+ s.Printf("@ 0x%8.8llx, value = ", addr);
+ variable_type->DumpValueInMemory (exe_ctx, &s, addr, addr_type, m_options.show_types, m_options.show_summary, m_options.debug);
+ }
+ }
+ break;
+ }
+ }
+ s.EOL();
+ }
+ }
+
+ void
+ DumpValueObject (CommandReturnObject &result,
+ ExecutionContextScope *exe_scope,
+ ValueObject *valobj,
+ const char *root_valobj_name,
+ uint32_t ptr_depth,
+ uint32_t curr_depth,
+ uint32_t max_depth,
+ bool use_objc)
+ {
+ if (valobj)
+ {
+ Stream &s = result.GetOutputStream();
+
+ //const char *loc_cstr = valobj->GetLocationAsCString();
+ if (m_options.show_location)
+ {
+ s.Printf("@ %s: ", valobj->GetLocationAsCString(exe_scope));
+ }
+ if (m_options.debug)
+ s.Printf ("%p ValueObject{%u} ", valobj, valobj->GetID());
+
+ s.Indent();
+
+ if (m_options.show_types)
+ s.Printf("(%s) ", valobj->GetTypeName().AsCString());
+
+ const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString("");
+ s.Printf ("%s = ", name_cstr);
+
+ const char *val_cstr = valobj->GetValueAsCString(exe_scope);
+ const char *err_cstr = valobj->GetError().AsCString();
+
+ if (err_cstr)
+ {
+ s.Printf ("error: %s\n", err_cstr);
+ }
+ else
+ {
+ const char *sum_cstr = valobj->GetSummaryAsCString(exe_scope);
+
+ const bool is_aggregate = ClangASTContext::IsAggregateType (valobj->GetOpaqueClangQualType());
+
+ if (val_cstr)
+ s.PutCString(val_cstr);
+
+ if (sum_cstr)
+ s.Printf(" %s", sum_cstr);
+
+ if (use_objc)
+ {
+ if (!ClangASTContext::IsPointerType (valobj->GetOpaqueClangQualType()))
+ return;
+
+ if (!valobj->GetValueIsValid())
+ return;
+
+ Process *process = exe_scope->CalculateProcess();
+
+ if (!process)
+ return;
+
+ Scalar scalar;
+
+ if (!Type::GetValueAsScalar (valobj->GetClangAST(),
+ valobj->GetOpaqueClangQualType(),
+ valobj->GetDataExtractor(),
+ 0,
+ valobj->GetByteSize(),
+ scalar))
+ return;
+
+ ConstString po_output;
+
+ ExecutionContext exe_ctx;
+ exe_scope->Calculate(exe_ctx);
+
+ Value val(scalar);
+ val.SetContext(Value::eContextTypeOpaqueClangQualType,
+ ClangASTContext::GetVoidPtrType(valobj->GetClangAST(), false));
+
+ if (!process->GetObjCObjectPrinter().PrintObject(po_output, val, exe_ctx))
+ return;
+
+ s.Printf("\n%s\n", po_output.GetCString());
+
+ return;
+ }
+
+
+ if (curr_depth < max_depth)
+ {
+ if (is_aggregate)
+ s.PutChar('{');
+
+ bool is_ptr_or_ref = ClangASTContext::IsPointerOrReferenceType (valobj->GetOpaqueClangQualType());
+
+ if (is_ptr_or_ref && ptr_depth == 0)
+ return;
+
+ const uint32_t num_children = valobj->GetNumChildren();
+ if (num_children)
+ {
+ s.IndentMore();
+ for (uint32_t idx=0; idx<num_children; ++idx)
+ {
+ ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
+ if (child_sp.get())
+ {
+ s.EOL();
+ DumpValueObject (result,
+ exe_scope,
+ child_sp.get(),
+ NULL,
+ is_ptr_or_ref ? ptr_depth - 1 : ptr_depth,
+ curr_depth + 1,
+ max_depth,
+ false);
+ if (idx + 1 < num_children)
+ s.PutChar(',');
+ }
+ }
+ s.IndentLess();
+ }
+ if (is_aggregate)
+ {
+ s.EOL();
+ s.Indent("}");
+ }
+ }
+ else
+ {
+ if (is_aggregate)
+ {
+ s.PutCString("{...}");
+ }
+ }
+
+ }
+ }
+ }
+
+ virtual bool
+ Execute (Args& command,
+ CommandContext *context,
+ CommandInterpreter *interpreter,
+ CommandReturnObject &result)
+ {
+ ExecutionContext exe_ctx(context->GetExecutionContext());
+ if (exe_ctx.frame == NULL)
+ {
+ result.AppendError ("invalid frame");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ else
+ {
+ VariableList variable_list;
+
+ SymbolContext frame_sc = exe_ctx.frame->GetSymbolContext (eSymbolContextEverything);
+ if (exe_ctx.frame && frame_sc.block)
+ frame_sc.block->AppendVariables(true, true, &variable_list);
+ VariableSP var_sp;
+ ValueObjectSP valobj_sp;
+ //ValueObjectList &valobj_list = exe_ctx.frame->GetValueObjectList();
+ const char *name_cstr = NULL;
+ size_t idx;
+ if (!m_options.globals.empty())
+ {
+ uint32_t fail_count = 0;
+ Target *target = context->GetTarget();
+ if (target)
+ {
+ const size_t num_globals = m_options.globals.size();
+ for (idx = 0; idx < num_globals; ++idx)
+ {
+ VariableList global_var_list;
+ const uint32_t num_matching_globals = target->GetImages().FindGlobalVariables (m_options.globals[idx], true, UINT32_MAX, global_var_list);
+
+ if (num_matching_globals == 0)
+ {
+ ++fail_count;
+ result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", m_options.globals[idx].AsCString());
+ }
+ else
+ {
+ for (uint32_t global_idx=0; global_idx<num_matching_globals; ++global_idx)
+ {
+ var_sp = global_var_list.GetVariableAtIndex(global_idx);
+ if (var_sp)
+ {
+ valobj_sp = exe_ctx.frame->GetValueObjectList().FindValueObjectByValueName (m_options.globals[idx].AsCString());
+ if (!valobj_sp)
+ valobj_sp.reset (new ValueObjectVariable (var_sp));
+
+ if (valobj_sp)
+ {
+ exe_ctx.frame->GetValueObjectList().Append (valobj_sp);
+ DumpValueObject (result, exe_ctx.frame, valobj_sp.get(), name_cstr, m_options.ptr_depth, 0, m_options.max_depth, false);
+ result.GetOutputStream().EOL();
+ }
+ }
+ }
+ }
+ }
+ }
+ if (fail_count)
+ {
+ result.SetStatus (eReturnStatusFailed);
+ }
+ }
+
+ if (command.GetArgumentCount() > 0)
+ {
+ // If we have any args to the variable command, we will make
+ // variable objects from them...
+ for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx)
+ {
+ uint32_t ptr_depth = m_options.ptr_depth;
+ // If first character is a '*', then show pointer contents
+ if (name_cstr[0] == '*')
+ {
+ ++ptr_depth;
+ name_cstr++; // Skip the '*'
+ }
+
+ std::string var_path (name_cstr);
+ size_t separator_idx = var_path.find_first_of(".-[");
+
+ ConstString name_const_string;
+ if (separator_idx == std::string::npos)
+ name_const_string.SetCString (var_path.c_str());
+ else
+ name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
+
+ var_sp = variable_list.FindVariable(name_const_string);
+ if (var_sp)
+ {
+ //DumpVariable (result, &exe_ctx, var_sp.get());
+ // TODO: redo history variables using a different map
+// if (var_path[0] == '$')
+// valobj_sp = valobj_list.FindValueObjectByValueObjectName (name_const_string.GetCString());
+// else
+ valobj_sp = exe_ctx.frame->GetValueObjectList().FindValueObjectByValueName (name_const_string.GetCString());
+
+ if (!valobj_sp)
+ {
+ valobj_sp.reset (new ValueObjectVariable (var_sp));
+ exe_ctx.frame->GetValueObjectList().Append (valobj_sp);
+ }
+
+ var_path.erase (0, name_const_string.GetLength ());
+ // We are dumping at least one child
+ while (separator_idx != std::string::npos)
+ {
+ // Calculate the next separator index ahead of time
+ ValueObjectSP child_valobj_sp;
+ const char separator_type = var_path[0];
+ switch (separator_type)
+ {
+
+ case '-':
+ if (var_path.size() >= 2 && var_path[1] != '>')
+ {
+ result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
+ var_path.c_str());
+ var_path.clear();
+ valobj_sp.reset();
+ break;
+ }
+ var_path.erase (0, 1); // Remove the '-'
+ // Fall through
+ case '.':
+ {
+ var_path.erase (0, 1); // Remove the '.' or '>'
+ separator_idx = var_path.find_first_of(".-[");
+ ConstString child_name;
+ if (separator_idx == std::string::npos)
+ child_name.SetCString (var_path.c_str());
+ else
+ child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
+
+ child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
+ if (!child_valobj_sp)
+ {
+ result.GetErrorStream().Printf ("error: can't find child of '%s' named '%s'\n",
+ valobj_sp->GetName().AsCString(),
+ child_name.GetCString());
+ var_path.clear();
+ valobj_sp.reset();
+ break;
+ }
+ // Remove the child name from the path
+ var_path.erase(0, child_name.GetLength());
+ }
+ break;
+
+ case '[':
+ // Array member access, or treating pointer as an array
+ if (var_path.size() > 2) // Need at least two brackets and a number
+ {
+ char *end = NULL;
+ int32_t child_index = ::strtol (&var_path[1], &end, 0);
+ if (end && *end == ']')
+ {
+
+ if (valobj_sp->IsPointerType ())
+ {
+ child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
+ }
+ else
+ {
+ child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
+ }
+
+ if (!child_valobj_sp)
+ {
+ result.GetErrorStream().Printf ("error: invalid array index %u in '%s'\n",
+ child_index,
+ valobj_sp->GetName().AsCString());
+ var_path.clear();
+ valobj_sp.reset();
+ break;
+ }
+
+ // Erase the array member specification '[%i]' where %i is the array index
+ var_path.erase(0, (end - var_path.c_str()) + 1);
+ separator_idx = var_path.find_first_of(".-[");
+
+ // Break out early from the switch since we were able to find the child member
+ break;
+ }
+ }
+ result.GetErrorStream().Printf ("error: invalid array member specification for '%s' starting at '%s'\n",
+ valobj_sp->GetName().AsCString(),
+ var_path.c_str());
+ var_path.clear();
+ valobj_sp.reset();
+ break;
+
+ break;
+
+ default:
+ result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
+ var_path.c_str());
+ var_path.clear();
+ valobj_sp.reset();
+ separator_idx = std::string::npos;
+ break;
+ }
+
+ if (child_valobj_sp)
+ valobj_sp = child_valobj_sp;
+
+ if (var_path.empty())
+ break;
+
+ }
+
+ if (valobj_sp)
+ {
+ DumpValueObject (result, exe_ctx.frame, valobj_sp.get(), name_cstr, ptr_depth, 0, m_options.max_depth, m_options.use_objc);
+ result.GetOutputStream().EOL();
+ }
+ }
+ else
+ {
+ result.GetErrorStream().Printf ("error: unable to find any variables named '%s'\n", name_cstr);
+ var_path.clear();
+ }
+ }
+ }
+ else
+ {
+
+ if (m_options.show_globals)
+ {
+ if (frame_sc.comp_unit)
+ {
+ variable_list.AddVariables (frame_sc.comp_unit->GetVariableList(true).get());
+ }
+ }
+
+ const uint32_t num_variables = variable_list.GetSize();
+
+ if (num_variables > 0)
+ {
+ for (uint32_t i=0; i<num_variables; i++)
+ {
+ Variable *variable = variable_list.GetVariableAtIndex(i).get();
+ bool dump_variable = true;
+
+ switch (variable->GetScope())
+ {
+ case eValueTypeVariableGlobal:
+ dump_variable = m_options.show_globals;
+ if (dump_variable && m_options.show_scope)
+ result.GetOutputStream().PutCString("GLOBAL: ");
+ break;
+
+ case eValueTypeVariableStatic:
+ dump_variable = m_options.show_globals;
+ if (dump_variable && m_options.show_scope)
+ result.GetOutputStream().PutCString("STATIC: ");
+ break;
+
+ case eValueTypeVariableArgument:
+ dump_variable = m_options.show_args;
+ if (dump_variable && m_options.show_scope)
+ result.GetOutputStream().PutCString(" ARG: ");
+ break;
+
+ case eValueTypeVariableLocal:
+ dump_variable = m_options.show_locals;
+ if (dump_variable && m_options.show_scope)
+ result.GetOutputStream().PutCString(" LOCAL: ");
+ break;
+
+ default:
+ break;
+ }
+
+ if (dump_variable)
+ DumpVariable (result, &exe_ctx, variable);
+ }
+ }
+ }
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ }
+ return result.Succeeded();
+ }
+protected:
+
+ CommandOptions m_options;
+};
+
+lldb::OptionDefinition
+CommandObjectVariableList::CommandOptions::g_option_table[] =
+{
+{ 0, false, "debug", 'D', no_argument, NULL, 0, NULL, "Show verbose debug information."},
+{ 0, false, "depth", 'd', required_argument, NULL, 0, "<count>", "Set the max recurse depth when dumping aggregate types (default is infinity)."},
+{ 0, false, "globals", 'g', no_argument, NULL, 0, NULL, "List global and static variables for the current stack frame source file."},
+{ 0, false, "global", 'G', required_argument, NULL, 0, NULL, "Find a global variable by name (which might not be in the current stack frame source file)."},
+{ 0, false, "location", 'L', no_argument, NULL, 0, NULL, "Show variable location information."},
+{ 0, false, "name", 'n', required_argument, NULL, 0, "<name>", "Lookup a variable by name or regex (--regex) for the current execution context."},
+{ 0, false, "no-args", 'a', no_argument, NULL, 0, NULL, "Omit function arguments."},
+{ 0, false, "no-locals", 'l', no_argument, NULL, 0, NULL, "Omit local variables."},
+{ 0, false, "no-types", 't', no_argument, NULL, 0, NULL, "Omit variable type names."},
+{ 0, false, "no-summary", 'y', no_argument, NULL, 0, NULL, "Omit summary information."},
+{ 0, false, "scope", 's', no_argument, NULL, 0, NULL, "Show variable scope (argument, local, global, static)."},
+{ 0, false, "objc", 'o', no_argument, NULL, 0, NULL, "When looking up a variable by name (--name), print as an Objective-C object."},
+{ 0, false, "ptr-depth", 'p', required_argument, NULL, 0, "<count>", "The number of pointers to be traversed when dumping values (default is zero)."},
+{ 0, false, "regex", 'r', no_argument, NULL, 0, NULL, "The <name> argument for name lookups are regular expressions."},
+{ 0, false, NULL, 0, 0, NULL, NULL, NULL, NULL }
+};
+
+//----------------------------------------------------------------------
+// CommandObjectVariable constructor
+//----------------------------------------------------------------------
+CommandObjectVariable::CommandObjectVariable(CommandInterpreter *interpreter) :
+ CommandObjectMultiword ("variable",
+ "Access program arguments, locals, static and global variables.",
+ "variable [list] ...")
+{
+ LoadSubCommand (CommandObjectSP (new CommandObjectVariableList ()), "list", interpreter);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+CommandObjectVariable::~CommandObjectVariable()
+{
+}
+
+
+
+
diff --git a/lldb/source/Commands/CommandObjectVariable.h b/lldb/source/Commands/CommandObjectVariable.h
new file mode 100644
index 00000000000..65869c73d72
--- /dev/null
+++ b/lldb/source/Commands/CommandObjectVariable.h
@@ -0,0 +1,43 @@
+//===-- CommandObjectVariable.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CommandObjectVariable_h_
+#define liblldb_CommandObjectVariable_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+
+namespace lldb_private {
+
+//-------------------------------------------------------------------------
+// CommandObjectImage
+//-------------------------------------------------------------------------
+
+class CommandObjectVariable : public CommandObjectMultiword
+{
+public:
+
+ CommandObjectVariable (CommandInterpreter *iterpreter);
+
+ virtual
+ ~CommandObjectVariable ();
+
+private:
+ //------------------------------------------------------------------
+ // For CommandObjectVariable only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (CommandObjectVariable);
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_CommandObjectVariable_h_
OpenPOWER on IntegriCloud