llvm-project/lldb/source/Commands/CommandObjectFrame.cpp

689 lines
28 KiB
C++
Raw Normal View History

//===-- 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/DataVisualization.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
#include "lldb/Interpreter/OptionGroupVariable.h"
#include "lldb/Symbol/ClangASTType.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/Thread.h"
#include "lldb/Target/Target.h"
using namespace lldb;
using namespace lldb_private;
#pragma mark CommandObjectFrameInfo
//-------------------------------------------------------------------------
// CommandObjectFrameInfo
//-------------------------------------------------------------------------
class CommandObjectFrameInfo : public CommandObject
{
public:
CommandObjectFrameInfo (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"frame info",
"List information about the currently selected frame in the current thread.",
"frame info",
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
{
}
~CommandObjectFrameInfo ()
{
}
bool
Execute (Args& command,
CommandReturnObject &result)
{
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 13:54:46 +08:00
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (exe_ctx.frame)
{
There are now to new "settings set" variables that live in each debugger instance: settings set frame-format <string> settings set thread-format <string> This allows users to control the information that is seen when dumping threads and frames. The default values are set such that they do what they used to do prior to changing over the the user defined formats. This allows users with terminals that can display color to make different items different colors using the escape control codes. A few alias examples that will colorize your thread and frame prompts are: settings set frame-format 'frame #${frame.index}: \033[0;33m${frame.pc}\033[0m{ \033[1;4;36m${module.file.basename}\033[0;36m ${function.name}{${function.pc-offset}}\033[0m}{ \033[0;35mat \033[1;35m${line.file.basename}:${line.number}}\033[0m\n' settings set thread-format 'thread #${thread.index}: \033[1;33mtid\033[0;33m = ${thread.id}\033[0m{, \033[0;33m${frame.pc}\033[0m}{ \033[1;4;36m${module.file.basename}\033[0;36m ${function.name}{${function.pc-offset}}\033[0m}{, \033[1;35mstop reason\033[0;35m = ${thread.stop-reason}\033[0m}{, \033[1;36mname = \033[0;36m${thread.name}\033[0m}{, \033[1;32mqueue = \033[0;32m${thread.queue}}\033[0m\n' A quick web search for "colorize terminal output" should allow you to see what you can do to make your output look like you want it. The "settings set" commands above can of course be added to your ~/.lldbinit file for permanent use. Changed the pure virtual void ExecutionContextScope::Calculate (ExecutionContext&); To: void ExecutionContextScope::CalculateExecutionContext (ExecutionContext&); I did this because this is a class that anything in the execution context heirarchy inherits from and "target->Calculate (exe_ctx)" didn't always tell you what it was really trying to do unless you look at the parameter. llvm-svn: 115485
2010-10-04 09:05:56 +08:00
exe_ctx.frame->DumpUsingSettingsFormat (&result.GetOutputStream());
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
{
result.AppendError ("no current frame");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
}
};
#pragma mark CommandObjectFrameSelect
//-------------------------------------------------------------------------
// CommandObjectFrameSelect
//-------------------------------------------------------------------------
class CommandObjectFrameSelect : public CommandObject
{
public:
class CommandOptions : public Options
{
public:
CommandOptions (CommandInterpreter &interpreter) :
Options(interpreter)
{
Added two new classes for command options: lldb_private::OptionGroup lldb_private::OptionGroupOptions OptionGroup lets you define a class that encapsulates settings that you want to reuse in multiple commands. It contains only the option definitions and the ability to set the option values, but it doesn't directly interface with the lldb_private::Options class that is the front end to all of the CommandObject option parsing. For that the OptionGroupOptions class can be used. It aggregates one or more OptionGroup objects and directs the option setting to the appropriate OptionGroup class. For an example of this, take a look at the CommandObjectFile and how it uses its "m_option_group" object shown below to be able to set values in both the FileOptionGroup and PlatformOptionGroup classes. The members used in CommandObjectFile are: OptionGroupOptions m_option_group; FileOptionGroup m_file_options; PlatformOptionGroup m_platform_options; Then in the constructor for CommandObjectFile you can combine the option settings. The code below shows a simplified version of the constructor: CommandObjectFile::CommandObjectFile(CommandInterpreter &interpreter) : CommandObject (...), m_option_group (interpreter), m_file_options (), m_platform_options(true) { m_option_group.Append (&m_file_options); m_option_group.Append (&m_platform_options); m_option_group.Finalize(); } We append the m_file_options and then the m_platform_options and then tell the option group the finalize the results. This allows the m_option_group to become the organizer of our prefs and after option parsing we end up with valid preference settings in both the m_file_options and m_platform_options objects. This also allows any other commands to use the FileOptionGroup and PlatformOptionGroup classes to implement options for their commands. Renamed: virtual void Options::ResetOptionValues(); to: virtual void Options::OptionParsingStarting(); And implemented a new callback named: virtual Error Options::OptionParsingFinished(); This allows Options subclasses to verify that the options all go together after all of the options have been specified and gives the chance for the command object to return an error. It also gives a chance to take all of the option values and produce or initialize objects after all options have completed parsing. Modfied: virtual Error SetOptionValue (int option_idx, const char *option_arg) = 0; to be: virtual Error SetOptionValue (uint32_t option_idx, const char *option_arg) = 0; (option_idx is now unsigned). llvm-svn: 129415
2011-04-13 08:18:08 +08:00
OptionParsingStarting ();
}
virtual
~CommandOptions ()
{
}
virtual Error
Added two new classes for command options: lldb_private::OptionGroup lldb_private::OptionGroupOptions OptionGroup lets you define a class that encapsulates settings that you want to reuse in multiple commands. It contains only the option definitions and the ability to set the option values, but it doesn't directly interface with the lldb_private::Options class that is the front end to all of the CommandObject option parsing. For that the OptionGroupOptions class can be used. It aggregates one or more OptionGroup objects and directs the option setting to the appropriate OptionGroup class. For an example of this, take a look at the CommandObjectFile and how it uses its "m_option_group" object shown below to be able to set values in both the FileOptionGroup and PlatformOptionGroup classes. The members used in CommandObjectFile are: OptionGroupOptions m_option_group; FileOptionGroup m_file_options; PlatformOptionGroup m_platform_options; Then in the constructor for CommandObjectFile you can combine the option settings. The code below shows a simplified version of the constructor: CommandObjectFile::CommandObjectFile(CommandInterpreter &interpreter) : CommandObject (...), m_option_group (interpreter), m_file_options (), m_platform_options(true) { m_option_group.Append (&m_file_options); m_option_group.Append (&m_platform_options); m_option_group.Finalize(); } We append the m_file_options and then the m_platform_options and then tell the option group the finalize the results. This allows the m_option_group to become the organizer of our prefs and after option parsing we end up with valid preference settings in both the m_file_options and m_platform_options objects. This also allows any other commands to use the FileOptionGroup and PlatformOptionGroup classes to implement options for their commands. Renamed: virtual void Options::ResetOptionValues(); to: virtual void Options::OptionParsingStarting(); And implemented a new callback named: virtual Error Options::OptionParsingFinished(); This allows Options subclasses to verify that the options all go together after all of the options have been specified and gives the chance for the command object to return an error. It also gives a chance to take all of the option values and produce or initialize objects after all options have completed parsing. Modfied: virtual Error SetOptionValue (int option_idx, const char *option_arg) = 0; to be: virtual Error SetOptionValue (uint32_t option_idx, const char *option_arg) = 0; (option_idx is now unsigned). llvm-svn: 129415
2011-04-13 08:18:08 +08:00
SetOptionValue (uint32_t option_idx, const char *option_arg)
{
Error error;
bool success = false;
char short_option = (char) m_getopt_table[option_idx].val;
switch (short_option)
{
case 'r':
relative_frame_offset = Args::StringToSInt32 (option_arg, INT32_MIN, 0, &success);
if (!success)
error.SetErrorStringWithFormat ("invalid frame offset argument '%s'.\n", option_arg);
break;
default:
error.SetErrorStringWithFormat ("Invalid short option character '%c'.\n", short_option);
break;
}
return error;
}
void
Added two new classes for command options: lldb_private::OptionGroup lldb_private::OptionGroupOptions OptionGroup lets you define a class that encapsulates settings that you want to reuse in multiple commands. It contains only the option definitions and the ability to set the option values, but it doesn't directly interface with the lldb_private::Options class that is the front end to all of the CommandObject option parsing. For that the OptionGroupOptions class can be used. It aggregates one or more OptionGroup objects and directs the option setting to the appropriate OptionGroup class. For an example of this, take a look at the CommandObjectFile and how it uses its "m_option_group" object shown below to be able to set values in both the FileOptionGroup and PlatformOptionGroup classes. The members used in CommandObjectFile are: OptionGroupOptions m_option_group; FileOptionGroup m_file_options; PlatformOptionGroup m_platform_options; Then in the constructor for CommandObjectFile you can combine the option settings. The code below shows a simplified version of the constructor: CommandObjectFile::CommandObjectFile(CommandInterpreter &interpreter) : CommandObject (...), m_option_group (interpreter), m_file_options (), m_platform_options(true) { m_option_group.Append (&m_file_options); m_option_group.Append (&m_platform_options); m_option_group.Finalize(); } We append the m_file_options and then the m_platform_options and then tell the option group the finalize the results. This allows the m_option_group to become the organizer of our prefs and after option parsing we end up with valid preference settings in both the m_file_options and m_platform_options objects. This also allows any other commands to use the FileOptionGroup and PlatformOptionGroup classes to implement options for their commands. Renamed: virtual void Options::ResetOptionValues(); to: virtual void Options::OptionParsingStarting(); And implemented a new callback named: virtual Error Options::OptionParsingFinished(); This allows Options subclasses to verify that the options all go together after all of the options have been specified and gives the chance for the command object to return an error. It also gives a chance to take all of the option values and produce or initialize objects after all options have completed parsing. Modfied: virtual Error SetOptionValue (int option_idx, const char *option_arg) = 0; to be: virtual Error SetOptionValue (uint32_t option_idx, const char *option_arg) = 0; (option_idx is now unsigned). llvm-svn: 129415
2011-04-13 08:18:08 +08:00
OptionParsingStarting ()
{
relative_frame_offset = INT32_MIN;
}
const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
int32_t relative_frame_offset;
};
CommandObjectFrameSelect (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"frame select",
"Select a frame by index from within the current thread and make it the current frame.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
m_options (interpreter)
{
CommandArgumentEntry arg;
CommandArgumentData index_arg;
// Define the first (and only) variant of this arg.
index_arg.arg_type = eArgTypeFrameIndex;
index_arg.arg_repetition = eArgRepeatOptional;
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (index_arg);
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg);
}
~CommandObjectFrameSelect ()
{
}
virtual
Options *
GetOptions ()
{
return &m_options;
}
bool
Execute (Args& command,
CommandReturnObject &result)
{
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 13:54:46 +08:00
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
if (exe_ctx.thread)
{
const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
uint32_t frame_idx = UINT32_MAX;
if (m_options.relative_frame_offset != INT32_MIN)
{
// The one and only argument is a signed relative frame index
frame_idx = exe_ctx.thread->GetSelectedFrameIndex ();
if (frame_idx == UINT32_MAX)
frame_idx = 0;
if (m_options.relative_frame_offset < 0)
{
if (frame_idx >= -m_options.relative_frame_offset)
frame_idx += m_options.relative_frame_offset;
else
frame_idx = 0;
}
else if (m_options.relative_frame_offset > 0)
{
if (num_frames - frame_idx > m_options.relative_frame_offset)
frame_idx += m_options.relative_frame_offset;
else
frame_idx = num_frames - 1;
}
}
else
{
if (command.GetArgumentCount() == 1)
{
const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
}
else
{
result.AppendError ("invalid arguments.\n");
m_options.GenerateOptionUsage (result.GetErrorStream(), this);
}
}
if (frame_idx < num_frames)
{
exe_ctx.thread->SetSelectedFrameByIndex (frame_idx);
exe_ctx.frame = exe_ctx.thread->GetSelectedFrame ().get();
if (exe_ctx.frame)
{
bool already_shown = false;
SymbolContext frame_sc(exe_ctx.frame->GetSymbolContext(eSymbolContextLineEntry));
if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
{
already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
}
Centralized a lot of the status information for processes, threads, and stack frame down in the lldb_private::Process, lldb_private::Thread, lldb_private::StackFrameList and the lldb_private::StackFrame classes. We had some command line commands that had duplicate versions of the process status output ("thread list" and "process status" for example). Removed the "file" command and placed it where it should have been: "target create". Made an alias for "file" to "target create" so we stay compatible with GDB commands. We can now have multple usable targets in lldb at the same time. This is nice for comparing two runs of a program or debugging more than one binary at the same time. The new command is "target select <target-idx>" and also to see a list of the current targets you can use the new "target list" command. The flow in a debug session can be: (lldb) target create /path/to/exe/a.out (lldb) breakpoint set --name main (lldb) run ... hit breakpoint (lldb) target create /bin/ls (lldb) run /tmp Process 36001 exited with status = 0 (0x00000000) (lldb) target list Current targets: target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped ) * target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited ) (lldb) target select 0 Current targets: * target #0: /tmp/args/a.out ( arch=x86_64-apple-darwin, platform=localhost, pid=35999, state=stopped ) target #1: /bin/ls ( arch=x86_64-apple-darwin, platform=localhost, pid=36001, state=exited ) (lldb) bt * thread #1: tid = 0x2d03, 0x0000000100000b9a a.out`main + 42 at main.c:16, stop reason = breakpoint 1.1 frame #0: 0x0000000100000b9a a.out`main + 42 at main.c:16 frame #1: 0x0000000100000b64 a.out`start + 52 Above we created a target for "a.out" and ran and hit a breakpoint at "main". Then we created a new target for /bin/ls and ran it. Then we listed the targest and selected our original "a.out" program, so we showed two concurent debug sessions going on at the same time. llvm-svn: 129695
2011-04-18 16:33:37 +08:00
bool show_frame_info = true;
bool show_source = !already_shown;
uint32_t source_lines_before = 3;
uint32_t source_lines_after = 3;
if (exe_ctx.frame->GetStatus(result.GetOutputStream(),
show_frame_info,
show_source,
source_lines_before,
source_lines_after))
{
result.SetStatus (eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
}
}
result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
}
else
{
result.AppendError ("no current thread");
}
result.SetStatus (eReturnStatusFailed);
return false;
}
protected:
CommandOptions m_options;
};
OptionDefinition
CommandObjectFrameSelect::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "relative", 'r', required_argument, NULL, 0, eArgTypeOffset, "A relative frame index offset from the current frame index."},
{ 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
};
#pragma mark CommandObjectFrameVariable
//----------------------------------------------------------------------
// List images with associated information
//----------------------------------------------------------------------
class CommandObjectFrameVariable : public CommandObject
{
public:
class OptionGroupFrameVariable : public OptionGroup
{
public:
OptionGroupFrameVariable ()
{
}
virtual
~OptionGroupFrameVariable ()
{
}
virtual uint32_t
GetNumDefinitions ();
virtual const OptionDefinition*
GetDefinitions ()
{
return g_option_table;
}
virtual Error
SetOptionValue (CommandInterpreter &interpreter,
uint32_t option_idx,
const char *option_arg)
{
Error error;
char short_option = (char) g_option_table[option_idx].short_option;
switch (short_option)
{
case 'r': use_regex = true; break;
case 'a': show_args = false; break;
case 'l': show_locals = false; break;
case 'g': show_globals = true; break;
case 'c': show_decl = true; break;
case 'f': error = Args::StringToFormat(option_arg, format, NULL); break;
case 'G':
globals.push_back(ConstString (option_arg));
break;
case 's':
show_scope = true;
break;
default:
error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
break;
}
return error;
}
virtual void
OptionParsingStarting (CommandInterpreter &interpreter)
{
show_args = true;
show_decl = false;
Added more platform support. There are now some new commands: platform status -- gets status information for the selected platform platform create <platform-name> -- creates a new instance of a remote platform platform list -- list all available platforms platform select -- select a platform instance as the current platform (not working yet) When using "platform create" it will create a remote platform and make it the selected platform. For instances for iPhone OS debugging on Mac OS X one can do: (lldb) platform create remote-ios --sdk-version=4.0 Remote platform: iOS platform SDK version: 4.0 SDK path: "/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0" Not connected to a remote device. (lldb) file ~/Documents/a.out Current executable set to '~/Documents/a.out' (armv6). (lldb) image list [ 0] /Volumes/work/gclayton/Documents/devb/attach/a.out [ 1] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/dyld [ 2] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/libSystem.B.dylib Note that this is all happening prior to running _or_ connecting to a remote platform. Once connected to a remote platform the OS version might change which means we will need to update our dependecies. Also once we run, we will need to match up the actualy binaries with the actualy UUID's to files in the SDK, or download and cache them locally. This is just the start of the remote platforms, but this modification is the first iteration in getting the platforms really doing something. llvm-svn: 127934
2011-03-19 09:12:21 +08:00
format = eFormatDefault;
show_globals = false;
show_locals = true;
use_regex = false;
show_scope = false;
globals.clear();
}
// Options table: Required for subclasses of Options.
static OptionDefinition g_option_table[];
bool use_regex:1,
show_args:1,
show_locals:1,
show_globals:1,
show_scope:1,
show_decl:1;
Added more platform support. There are now some new commands: platform status -- gets status information for the selected platform platform create <platform-name> -- creates a new instance of a remote platform platform list -- list all available platforms platform select -- select a platform instance as the current platform (not working yet) When using "platform create" it will create a remote platform and make it the selected platform. For instances for iPhone OS debugging on Mac OS X one can do: (lldb) platform create remote-ios --sdk-version=4.0 Remote platform: iOS platform SDK version: 4.0 SDK path: "/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0" Not connected to a remote device. (lldb) file ~/Documents/a.out Current executable set to '~/Documents/a.out' (armv6). (lldb) image list [ 0] /Volumes/work/gclayton/Documents/devb/attach/a.out [ 1] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/dyld [ 2] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/libSystem.B.dylib Note that this is all happening prior to running _or_ connecting to a remote platform. Once connected to a remote platform the OS version might change which means we will need to update our dependecies. Also once we run, we will need to match up the actualy binaries with the actualy UUID's to files in the SDK, or download and cache them locally. This is just the start of the remote platforms, but this modification is the first iteration in getting the platforms really doing something. llvm-svn: 127934
2011-03-19 09:12:21 +08:00
lldb::Format format; // The format to use when dumping variables or children of variables
std::vector<ConstString> globals;
// Instance variables to hold the values for command options.
};
CommandObjectFrameVariable (CommandInterpreter &interpreter) :
CommandObject (interpreter,
"frame variable",
"Show frame variables. All argument and local variables "
"that are in scope will be shown when no arguments are given. "
"If any arguments are specified, they can be names of "
"argument, local, file static and file global variables. "
"Children of aggregate variables can be specified such as "
"'var->child.x'.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
m_option_group (interpreter),
m_option_variable(true), // Include the frame specific options by passing "true"
m_varobj_options()
{
CommandArgumentEntry arg;
CommandArgumentData var_name_arg;
// Define the first (and only) variant of this arg.
var_name_arg.arg_type = eArgTypeVarName;
var_name_arg.arg_repetition = eArgRepeatStar;
// There is only one variant this argument could be; put it into the argument entry.
arg.push_back (var_name_arg);
// Push the data for the first argument into the m_arguments vector.
m_arguments.push_back (arg);
m_option_group.Append (&m_option_variable, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Finalize();
}
virtual
~CommandObjectFrameVariable ()
{
}
virtual
Options *
GetOptions ()
{
return &m_option_group;
}
virtual bool
Execute
(
Args& command,
CommandReturnObject &result
)
{
Moved the execution context that was in the Debugger into the CommandInterpreter where it was always being used. Make sure that Modules can track their object file offsets correctly to allow opening of sub object files (like the "__commpage" on darwin). Modified the Platforms to be able to launch processes. The first part of this move is the platform soon will become the entity that launches your program and when it does, it uses a new ProcessLaunchInfo class which encapsulates all process launching settings. This simplifies the internal APIs needed for launching. I want to slowly phase out process launching from the process classes, so for now we can still launch just as we used to, but eventually the platform is the object that should do the launching. Modified the Host::LaunchProcess in the MacOSX Host.mm to correctly be able to launch processes with all of the new eLaunchFlag settings. Modified any code that was manually launching processes to use the Host::LaunchProcess functions. Fixed an issue where lldb_private::Args had implicitly defined copy constructors that could do the wrong thing. This has now been fixed by adding an appropriate copy constructor and assignment operator. Make sure we don't add empty ModuleSP entries to a module list. Fixed the commpage module creation on MacOSX, but we still need to train the MacOSX dynamic loader to not get rid of it when it doesn't have an entry in the all image infos. Abstracted many more calls from in ProcessGDBRemote down into the GDBRemoteCommunicationClient subclass to make the classes cleaner and more efficient. Fixed the default iOS ARM register context to be correct and also added support for targets that don't support the qThreadStopInfo packet by selecting the current thread (only if needed) and then sending a stop reply packet. Debugserver can now start up with a --unix-socket (-u for short) and can then bind to port zero and send the port it bound to to a listening process on the other end. This allows the GDB remote platform to spawn new GDB server instances (debugserver) to allow platform debugging. llvm-svn: 129351
2011-04-12 13:54:46 +08:00
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (exe_ctx.frame == NULL)
{
result.AppendError ("you must be stopped in a valid stack frame to view frame variables.");
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
Stream &s = result.GetOutputStream();
bool get_file_globals = true;
// Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList
// for the thread. So hold onto a shared pointer to the frame so it stays alive.
StackFrameSP frame_sp = exe_ctx.frame->GetSP();
VariableList *variable_list = frame_sp->GetVariableList (get_file_globals);
VariableSP var_sp;
ValueObjectSP valobj_sp;
const char *name_cstr = NULL;
size_t idx;
SummaryFormatSP summary_format_sp;
if (!m_option_variable.summary.empty())
DataVisualization::NamedSummaryFormats::Get(ConstString(m_option_variable.summary.c_str()), summary_format_sp);
ValueObject::DumpValueObjectOptions options;
options.SetPointerDepth(m_varobj_options.ptr_depth)
.SetMaximumDepth(m_varobj_options.max_depth)
.SetShowTypes(m_varobj_options.show_types)
.SetShowLocation(m_varobj_options.show_location)
.SetUseObjectiveC(m_varobj_options.use_objc)
.SetUseDynamicType(m_varobj_options.use_dynamic)
.SetUseSyntheticValue((lldb::SyntheticValueType)m_varobj_options.use_synth)
.SetFlatOutput(m_varobj_options.flat_output)
.SetOmitSummaryDepth(m_varobj_options.no_summary_depth)
.SetIgnoreCap(m_varobj_options.ignore_cap);
if (m_varobj_options.be_raw)
options.SetRawDisplay(true);
if (variable_list)
{
if (command.GetArgumentCount() > 0)
{
VariableList regex_var_list;
// 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)
{
if (m_option_variable.use_regex)
{
const uint32_t regex_start_index = regex_var_list.GetSize();
RegularExpression regex (name_cstr);
if (regex.Compile(name_cstr))
{
size_t num_matches = 0;
const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex,
regex_var_list,
num_matches);
if (num_new_regex_vars > 0)
{
for (uint32_t regex_idx = regex_start_index, end_index = regex_var_list.GetSize();
regex_idx < end_index;
++regex_idx)
{
var_sp = regex_var_list.GetVariableAtIndex (regex_idx);
if (var_sp)
{
valobj_sp = frame_sp->GetValueObjectForFrameVariable (var_sp, m_varobj_options.use_dynamic);
if (valobj_sp)
{
if (m_option_variable.format != eFormatDefault)
valobj_sp->SetFormat (m_option_variable.format);
Added more platform support. There are now some new commands: platform status -- gets status information for the selected platform platform create <platform-name> -- creates a new instance of a remote platform platform list -- list all available platforms platform select -- select a platform instance as the current platform (not working yet) When using "platform create" it will create a remote platform and make it the selected platform. For instances for iPhone OS debugging on Mac OS X one can do: (lldb) platform create remote-ios --sdk-version=4.0 Remote platform: iOS platform SDK version: 4.0 SDK path: "/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0" Not connected to a remote device. (lldb) file ~/Documents/a.out Current executable set to '~/Documents/a.out' (armv6). (lldb) image list [ 0] /Volumes/work/gclayton/Documents/devb/attach/a.out [ 1] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/dyld [ 2] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/libSystem.B.dylib Note that this is all happening prior to running _or_ connecting to a remote platform. Once connected to a remote platform the OS version might change which means we will need to update our dependecies. Also once we run, we will need to match up the actualy binaries with the actualy UUID's to files in the SDK, or download and cache them locally. This is just the start of the remote platforms, but this modification is the first iteration in getting the platforms really doing something. llvm-svn: 127934
2011-03-19 09:12:21 +08:00
if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile())
{
bool show_fullpaths = false;
bool show_module = true;
if (var_sp->DumpDeclaration(&s, show_fullpaths, show_module))
s.PutCString (": ");
}
if (summary_format_sp)
valobj_sp->SetCustomSummaryFormat(summary_format_sp);
ValueObject::DumpValueObject (result.GetOutputStream(),
valobj_sp.get(),
options);
}
}
}
}
else if (num_matches == 0)
{
result.GetErrorStream().Printf ("error: no variables matched the regular expression '%s'.\n", name_cstr);
}
}
else
{
char regex_error[1024];
if (regex.GetErrorAsCString(regex_error, sizeof(regex_error)))
result.GetErrorStream().Printf ("error: %s\n", regex_error);
else
result.GetErrorStream().Printf ("error: unkown regex error when compiling '%s'\n", name_cstr);
}
}
else
{
Error error;
uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember;
lldb::VariableSP var_sp;
valobj_sp = frame_sp->GetValueForVariableExpressionPath (name_cstr,
m_varobj_options.use_dynamic,
expr_path_options,
var_sp,
error);
if (valobj_sp)
{
if (m_option_variable.format != eFormatDefault)
valobj_sp->SetFormat (m_option_variable.format);
if (m_option_variable.show_decl && var_sp && var_sp->GetDeclaration ().GetFile())
{
var_sp->GetDeclaration ().DumpStopContext (&s, false);
s.PutCString (": ");
}
if (summary_format_sp)
valobj_sp->SetCustomSummaryFormat(summary_format_sp);
ValueObject::DumpValueObject (result.GetOutputStream(),
valobj_sp.get(),
valobj_sp->GetParent() ? name_cstr : NULL,
options);
}
else
{
const char *error_cstr = error.AsCString(NULL);
if (error_cstr)
result.GetErrorStream().Printf("error: %s\n", error_cstr);
else
result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", name_cstr);
}
}
}
}
else
{
const uint32_t num_variables = variable_list->GetSize();
if (num_variables > 0)
{
for (uint32_t i=0; i<num_variables; i++)
{
var_sp = variable_list->GetVariableAtIndex(i);
bool dump_variable = true;
switch (var_sp->GetScope())
{
case eValueTypeVariableGlobal:
dump_variable = m_option_variable.show_globals;
if (dump_variable && m_option_variable.show_scope)
s.PutCString("GLOBAL: ");
break;
case eValueTypeVariableStatic:
dump_variable = m_option_variable.show_globals;
if (dump_variable && m_option_variable.show_scope)
s.PutCString("STATIC: ");
break;
case eValueTypeVariableArgument:
dump_variable = m_option_variable.show_args;
if (dump_variable && m_option_variable.show_scope)
s.PutCString(" ARG: ");
break;
case eValueTypeVariableLocal:
dump_variable = m_option_variable.show_locals;
if (dump_variable && m_option_variable.show_scope)
s.PutCString(" LOCAL: ");
break;
default:
break;
}
if (dump_variable)
{
// Use the variable object code to make sure we are
// using the same APIs as the the public API will be
// using...
valobj_sp = frame_sp->GetValueObjectForFrameVariable (var_sp,
m_varobj_options.use_dynamic);
if (valobj_sp)
{
if (m_option_variable.format != eFormatDefault)
valobj_sp->SetFormat (m_option_variable.format);
Added more platform support. There are now some new commands: platform status -- gets status information for the selected platform platform create <platform-name> -- creates a new instance of a remote platform platform list -- list all available platforms platform select -- select a platform instance as the current platform (not working yet) When using "platform create" it will create a remote platform and make it the selected platform. For instances for iPhone OS debugging on Mac OS X one can do: (lldb) platform create remote-ios --sdk-version=4.0 Remote platform: iOS platform SDK version: 4.0 SDK path: "/Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0" Not connected to a remote device. (lldb) file ~/Documents/a.out Current executable set to '~/Documents/a.out' (armv6). (lldb) image list [ 0] /Volumes/work/gclayton/Documents/devb/attach/a.out [ 1] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/dyld [ 2] /Developer/Platforms/iPhoneOS.platform/DeviceSupport/4.0/Symbols/usr/lib/libSystem.B.dylib Note that this is all happening prior to running _or_ connecting to a remote platform. Once connected to a remote platform the OS version might change which means we will need to update our dependecies. Also once we run, we will need to match up the actualy binaries with the actualy UUID's to files in the SDK, or download and cache them locally. This is just the start of the remote platforms, but this modification is the first iteration in getting the platforms really doing something. llvm-svn: 127934
2011-03-19 09:12:21 +08:00
// When dumping all variables, don't print any variables
// that are not in scope to avoid extra unneeded output
if (valobj_sp->IsInScope ())
{
if (m_option_variable.show_decl && var_sp->GetDeclaration ().GetFile())
{
var_sp->GetDeclaration ().DumpStopContext (&s, false);
s.PutCString (": ");
}
if (summary_format_sp)
valobj_sp->SetCustomSummaryFormat(summary_format_sp);
ValueObject::DumpValueObject (result.GetOutputStream(),
valobj_sp.get(),
name_cstr,
options);
}
}
}
}
}
}
result.SetStatus (eReturnStatusSuccessFinishResult);
}
}
if (m_interpreter.TruncationWarningNecessary())
{
result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
m_cmd_name.c_str());
m_interpreter.TruncationWarningGiven();
}
return result.Succeeded();
}
protected:
OptionGroupOptions m_option_group;
OptionGroupVariable m_option_variable;
OptionGroupValueObjectDisplay m_varobj_options;
};
#pragma mark CommandObjectMultiwordFrame
//-------------------------------------------------------------------------
// CommandObjectMultiwordFrame
//-------------------------------------------------------------------------
CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter &interpreter) :
CommandObjectMultiword (interpreter,
"frame",
"A set of commands for operating on the current thread's frames.",
"frame <subcommand> [<subcommand-options>]")
{
LoadSubCommand ("info", CommandObjectSP (new CommandObjectFrameInfo (interpreter)));
LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter)));
LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter)));
}
CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
{
}