Expanded the flags that can be set for a command object in lldb_private::CommandObject. This list of available flags are:

enum
{
    //----------------------------------------------------------------------
    // eFlagRequiresTarget
    //
    // Ensures a valid target is contained in m_exe_ctx prior to executing
    // the command. If a target doesn't exist or is invalid, the command
    // will fail and CommandObject::GetInvalidTargetDescription() will be
    // returned as the error. CommandObject subclasses can override the
    // virtual function for GetInvalidTargetDescription() to provide custom
    // strings when needed.
    //----------------------------------------------------------------------
    eFlagRequiresTarget         = (1u << 0),
    //----------------------------------------------------------------------
    // eFlagRequiresProcess
    //
    // Ensures a valid process is contained in m_exe_ctx prior to executing
    // the command. If a process doesn't exist or is invalid, the command
    // will fail and CommandObject::GetInvalidProcessDescription() will be
    // returned as the error. CommandObject subclasses can override the
    // virtual function for GetInvalidProcessDescription() to provide custom
    // strings when needed.
    //----------------------------------------------------------------------
    eFlagRequiresProcess        = (1u << 1),
    //----------------------------------------------------------------------
    // eFlagRequiresThread
    //
    // Ensures a valid thread is contained in m_exe_ctx prior to executing
    // the command. If a thread doesn't exist or is invalid, the command
    // will fail and CommandObject::GetInvalidThreadDescription() will be
    // returned as the error. CommandObject subclasses can override the
    // virtual function for GetInvalidThreadDescription() to provide custom
    // strings when needed.
    //----------------------------------------------------------------------
    eFlagRequiresThread         = (1u << 2),
    //----------------------------------------------------------------------
    // eFlagRequiresFrame
    //
    // Ensures a valid frame is contained in m_exe_ctx prior to executing
    // the command. If a frame doesn't exist or is invalid, the command
    // will fail and CommandObject::GetInvalidFrameDescription() will be
    // returned as the error. CommandObject subclasses can override the
    // virtual function for GetInvalidFrameDescription() to provide custom
    // strings when needed.
    //----------------------------------------------------------------------
    eFlagRequiresFrame          = (1u << 3),
    //----------------------------------------------------------------------
    // eFlagRequiresRegContext
    //
    // Ensures a valid register context (from the selected frame if there
    // is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
    // is availble from m_exe_ctx prior to executing the command. If a
    // target doesn't exist or is invalid, the command will fail and
    // CommandObject::GetInvalidRegContextDescription() will be returned as
    // the error. CommandObject subclasses can override the virtual function
    // for GetInvalidRegContextDescription() to provide custom strings when
    // needed.
    //----------------------------------------------------------------------
    eFlagRequiresRegContext     = (1u << 4),
    //----------------------------------------------------------------------
    // eFlagTryTargetAPILock
    //
    // Attempts to acquire the target lock if a target is selected in the
    // command interpreter. If the command object fails to acquire the API
    // lock, the command will fail with an appropriate error message.
    //----------------------------------------------------------------------
    eFlagTryTargetAPILock       = (1u << 5),
    //----------------------------------------------------------------------
    // eFlagProcessMustBeLaunched
    //
    // Verifies that there is a launched process in m_exe_ctx, if there
    // isn't, the command will fail with an appropriate error message.
    //----------------------------------------------------------------------
    eFlagProcessMustBeLaunched  = (1u << 6),
    //----------------------------------------------------------------------
    // eFlagProcessMustBePaused
    //
    // Verifies that there is a paused process in m_exe_ctx, if there
    // isn't, the command will fail with an appropriate error message.
    //----------------------------------------------------------------------
    eFlagProcessMustBePaused    = (1u << 7)
};

Now each command object contains a "ExecutionContext m_exe_ctx;" member variable that gets initialized prior to running the command. The validity of the target objects in m_exe_ctx are checked to ensure that any target/process/thread/frame/reg context that are required are valid prior to executing the command. Each command object also contains a Mutex::Locker m_api_locker which gets used if eFlagTryTargetAPILock is set. This centralizes a lot of checking code that was previously and inconsistently implemented across many commands.

llvm-svn: 171990
This commit is contained in:
Greg Clayton 2013-01-09 19:44:40 +00:00
parent eb9ae76864
commit f9fc609fe7
16 changed files with 1111 additions and 1062 deletions

View File

@ -20,6 +20,8 @@
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/Flags.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/ExecutionContext.h"
namespace lldb_private {
@ -224,15 +226,91 @@ public:
bool
IsPairType (ArgumentRepetitionType arg_repeat_type);
enum
enum
{
eFlagProcessMustBeLaunched = (1 << 0),
eFlagProcessMustBePaused = (1 << 1)
//----------------------------------------------------------------------
// eFlagRequiresTarget
//
// Ensures a valid target is contained in m_exe_ctx prior to executing
// the command. If a target doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidTargetDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidTargetDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresTarget = (1u << 0),
//----------------------------------------------------------------------
// eFlagRequiresProcess
//
// Ensures a valid process is contained in m_exe_ctx prior to executing
// the command. If a process doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidProcessDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidProcessDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresProcess = (1u << 1),
//----------------------------------------------------------------------
// eFlagRequiresThread
//
// Ensures a valid thread is contained in m_exe_ctx prior to executing
// the command. If a thread doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidThreadDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidThreadDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresThread = (1u << 2),
//----------------------------------------------------------------------
// eFlagRequiresFrame
//
// Ensures a valid frame is contained in m_exe_ctx prior to executing
// the command. If a frame doesn't exist or is invalid, the command
// will fail and CommandObject::GetInvalidFrameDescription() will be
// returned as the error. CommandObject subclasses can override the
// virtual function for GetInvalidFrameDescription() to provide custom
// strings when needed.
//----------------------------------------------------------------------
eFlagRequiresFrame = (1u << 3),
//----------------------------------------------------------------------
// eFlagRequiresRegContext
//
// Ensures a valid register context (from the selected frame if there
// is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
// is availble from m_exe_ctx prior to executing the command. If a
// target doesn't exist or is invalid, the command will fail and
// CommandObject::GetInvalidRegContextDescription() will be returned as
// the error. CommandObject subclasses can override the virtual function
// for GetInvalidRegContextDescription() to provide custom strings when
// needed.
//----------------------------------------------------------------------
eFlagRequiresRegContext = (1u << 4),
//----------------------------------------------------------------------
// eFlagTryTargetAPILock
//
// Attempts to acquire the target lock if a target is selected in the
// command interpreter. If the command object fails to acquire the API
// lock, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagTryTargetAPILock = (1u << 5),
//----------------------------------------------------------------------
// eFlagProcessMustBeLaunched
//
// Verifies that there is a launched process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBeLaunched = (1u << 6),
//----------------------------------------------------------------------
// eFlagProcessMustBePaused
//
// Verifies that there is a paused process in m_exe_ctx, if there
// isn't, the command will fail with an appropriate error message.
//----------------------------------------------------------------------
eFlagProcessMustBePaused = (1u << 7)
};
bool
ParseOptions (Args& args,
CommandReturnObject &result);
ParseOptions (Args& args, CommandReturnObject &result);
void
SetCommandName (const char *name);
@ -374,19 +452,6 @@ public:
return m_flags;
}
//------------------------------------------------------------------
/// Check the command flags against the interpreter's current execution context.
///
/// @param[out] result
/// A command result object, if it is not okay to run the command this will be
/// filled in with a suitable error.
///
/// @return
/// \b true if it is okay to run this command, \b false otherwise.
//------------------------------------------------------------------
bool
CheckFlags (CommandReturnObject &result);
//------------------------------------------------------------------
/// Get the command that appropriate for a "repeat" of the current command.
///
@ -426,7 +491,56 @@ public:
Execute (const char *args_string, CommandReturnObject &result) = 0;
protected:
virtual const char *
GetInvalidTargetDescription()
{
return "invalid target, create a target using the 'target create' command";
}
virtual const char *
GetInvalidProcessDescription()
{
return "invalid process";
}
virtual const char *
GetInvalidThreadDescription()
{
return "invalid thread";
}
virtual const char *
GetInvalidFrameDescription()
{
return "invalid frame";
}
virtual const char *
GetInvalidRegContextDescription ()
{
return "invalid frame, no registers";
}
//------------------------------------------------------------------
/// Check the command to make sure anything required by this
/// command is available.
///
/// @param[out] result
/// A command result object, if it is not okay to run the command
/// this will be filled in with a suitable error.
///
/// @return
/// \b true if it is okay to run this command, \b false otherwise.
//------------------------------------------------------------------
bool
CheckRequirements (CommandReturnObject &result);
void
Cleanup ();
CommandInterpreter &m_interpreter;
ExecutionContext m_exe_ctx;
Mutex::Locker m_api_locker;
std::string m_cmd_name;
std::string m_cmd_help_short;
std::string m_cmd_help_long;

View File

@ -104,7 +104,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
ConstString target_triple;
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (!process)
{
result.AppendError ("Args found no process.");
@ -130,7 +130,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
return false;
}
Thread *thread = m_interpreter.GetExecutionContext ().GetThreadPtr();
Thread *thread = m_exe_ctx.GetThreadPtr();
if (!thread)
{

View File

@ -561,7 +561,7 @@ private:
// Then use the current stack frame's file.
if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line))
{
StackFrame *cur_frame = m_interpreter.GetExecutionContext().GetFramePtr();
StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
if (cur_frame == NULL)
{
result.AppendError ("No selected frame to use to find the default file.");

View File

@ -273,7 +273,6 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
if (m_options.show_mixed && m_options.num_lines_context == 0)
m_options.num_lines_context = 1;
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
// Always show the PC in the disassembly
uint32_t options = Disassembler::eOptionMarkPCAddress;
@ -294,7 +293,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.arch,
plugin_name,
exe_ctx,
m_exe_ctx,
name,
NULL, // Module *
m_options.num_instructions,
@ -313,7 +312,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
else
{
AddressRange range;
StackFrame *frame = exe_ctx.GetFramePtr();
StackFrame *frame = m_exe_ctx.GetFramePtr();
if (m_options.frame_line)
{
if (frame == NULL)
@ -414,7 +413,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.arch,
plugin_name,
exe_ctx,
m_exe_ctx,
range.GetBaseAddress(),
m_options.num_instructions,
m_options.show_mixed ? m_options.num_lines_context : 0,
@ -460,7 +459,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.arch,
plugin_name,
exe_ctx,
m_exe_ctx,
range,
m_options.num_instructions,
m_options.show_mixed ? m_options.num_lines_context : 0,

View File

@ -168,7 +168,7 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
"expression",
"Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
NULL,
eFlagProcessMustBePaused),
eFlagProcessMustBePaused | eFlagTryTargetAPILock),
m_option_group (interpreter),
m_format_options (eFormatDefault),
m_command_options (),
@ -315,7 +315,7 @@ CommandObjectExpression::EvaluateExpression
CommandReturnObject *result
)
{
Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
Target *target = m_exe_ctx.GetTargetPtr();
if (!target)
target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get();
@ -351,7 +351,7 @@ CommandObjectExpression::EvaluateExpression
.SetTimeoutUsec(m_command_options.timeout);
exe_results = target->EvaluateExpression (expr,
m_interpreter.GetExecutionContext().GetFramePtr(),
m_exe_ctx.GetFramePtr(),
result_valobj_sp,
options);
@ -360,7 +360,7 @@ CommandObjectExpression::EvaluateExpression
uint32_t start_frame = 0;
uint32_t num_frames = 1;
uint32_t num_frames_with_source = 0;
Thread *thread = m_interpreter.GetExecutionContext().GetThreadPtr();
Thread *thread = m_exe_ctx.GetThreadPtr();
if (thread)
{
thread->GetStatus (result->GetOutputStream(),
@ -370,7 +370,7 @@ CommandObjectExpression::EvaluateExpression
}
else
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process)
{
bool only_threads_with_stop_reason = true;

View File

@ -63,7 +63,10 @@ public:
"frame info",
"List information about the currently selected frame in the current thread.",
"frame info",
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
eFlagRequiresFrame |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused )
{
}
@ -73,21 +76,10 @@ public:
protected:
bool
DoExecute (Args& command,
CommandReturnObject &result)
DoExecute (Args& command, CommandReturnObject &result)
{
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame)
{
frame->DumpUsingSettingsFormat (&result.GetOutputStream());
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
{
result.AppendError ("no current frame");
result.SetStatus (eReturnStatusFailed);
}
m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat (&result.GetOutputStream());
result.SetStatus (eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
};
@ -162,7 +154,10 @@ public:
"frame select",
"Select a frame by index from within the current thread and make it the current frame.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
eFlagRequiresThread |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_options (interpreter)
{
CommandArgumentEntry arg;
@ -193,111 +188,104 @@ public:
protected:
bool
DoExecute (Args& command,
CommandReturnObject &result)
DoExecute (Args& command, CommandReturnObject &result)
{
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Thread *thread = exe_ctx.GetThreadPtr();
if (thread)
// No need to check "thread" for validity as eFlagRequiresThread ensures it is valid
Thread *thread = m_exe_ctx.GetThreadPtr();
uint32_t frame_idx = UINT32_MAX;
if (m_options.relative_frame_offset != INT32_MIN)
{
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 = thread->GetSelectedFrameIndex ();
if (frame_idx == UINT32_MAX)
frame_idx = 0;
if (m_options.relative_frame_offset < 0)
{
// The one and only argument is a signed relative frame index
frame_idx = 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
{
if (frame_idx == 0)
{
//If you are already at the bottom of the stack, then just warn and don't reset the frame.
result.AppendError("Already at the bottom of the stack");
result.SetStatus(eReturnStatusFailed);
return false;
}
else
frame_idx = 0;
}
}
else if (m_options.relative_frame_offset > 0)
{
// I don't want "up 20" where "20" takes you past the top of the stack to produce
// an error, but rather to just go to the top. So I have to count the stack here...
const uint32_t num_frames = thread->GetStackFrameCount();
if (num_frames - frame_idx > m_options.relative_frame_offset)
frame_idx += m_options.relative_frame_offset;
else
{
if (frame_idx == num_frames - 1)
{
//If we are already at the top of the stack, just warn and don't reset the frame.
result.AppendError("Already at the top of the stack");
result.SetStatus(eReturnStatusFailed);
return false;
}
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 if (command.GetArgumentCount() == 0)
{
frame_idx = thread->GetSelectedFrameIndex ();
if (frame_idx == UINT32_MAX)
{
frame_idx = 0;
}
}
if (frame_idx >= -m_options.relative_frame_offset)
frame_idx += m_options.relative_frame_offset;
else
{
result.AppendError ("invalid arguments.\n");
m_options.GenerateOptionUsage (result.GetErrorStream(), this);
if (frame_idx == 0)
{
//If you are already at the bottom of the stack, then just warn and don't reset the frame.
result.AppendError("Already at the bottom of the stack");
result.SetStatus(eReturnStatusFailed);
return false;
}
else
frame_idx = 0;
}
}
const bool broadcast = true;
bool success = thread->SetSelectedFrameByIndex (frame_idx, broadcast);
if (success)
else if (m_options.relative_frame_offset > 0)
{
exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame)
// I don't want "up 20" where "20" takes you past the top of the stack to produce
// an error, but rather to just go to the top. So I have to count the stack here...
const uint32_t num_frames = thread->GetStackFrameCount();
if (num_frames - frame_idx > m_options.relative_frame_offset)
frame_idx += m_options.relative_frame_offset;
else
{
bool already_shown = false;
SymbolContext frame_sc(frame->GetSymbolContext(eSymbolContextLineEntry));
if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
if (frame_idx == num_frames - 1)
{
already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
}
bool show_frame_info = true;
bool show_source = !already_shown;
if (frame->GetStatus (result.GetOutputStream(), show_frame_info, show_source))
{
result.SetStatus (eReturnStatusSuccessFinishResult);
return result.Succeeded();
//If we are already at the top of the stack, just warn and don't reset the frame.
result.AppendError("Already at the top of the stack");
result.SetStatus(eReturnStatusFailed);
return false;
}
else
frame_idx = num_frames - 1;
}
}
result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
}
else
else
{
result.AppendError ("no current thread");
if (command.GetArgumentCount() == 1)
{
const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
}
else if (command.GetArgumentCount() == 0)
{
frame_idx = thread->GetSelectedFrameIndex ();
if (frame_idx == UINT32_MAX)
{
frame_idx = 0;
}
}
else
{
result.AppendError ("invalid arguments.\n");
m_options.GenerateOptionUsage (result.GetErrorStream(), this);
}
}
const bool broadcast = true;
bool success = thread->SetSelectedFrameByIndex (frame_idx, broadcast);
if (success)
{
m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
StackFrame *frame = m_exe_ctx.GetFramePtr();
if (frame)
{
bool already_shown = false;
SymbolContext frame_sc(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);
}
bool show_frame_info = true;
bool show_source = !already_shown;
if (frame->GetStatus (result.GetOutputStream(), show_frame_info, show_source))
{
result.SetStatus (eReturnStatusSuccessFinishResult);
return result.Succeeded();
}
}
}
result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
result.SetStatus (eReturnStatusFailed);
return false;
}
@ -331,7 +319,10 @@ public:
"Children of aggregate variables can be specified such as "
"'var->child.x'.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
eFlagRequiresFrame |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused),
m_option_group (interpreter),
m_option_variable(true), // Include the frame specific options by passing "true"
m_option_format (eFormatDefault),
@ -372,14 +363,8 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame == NULL)
{
result.AppendError ("you must be stopped in a valid stack frame to view frame variables.");
result.SetStatus (eReturnStatusFailed);
return false;
}
// No need to check "frame" for validity as eFlagRequiresFrame ensures it is valid
StackFrame *frame = m_exe_ctx.GetFramePtr();
Stream &s = result.GetOutputStream();

View File

@ -298,7 +298,7 @@ public:
"memory read",
"Read from the memory of the process being debugged.",
NULL,
eFlagProcessMustBePaused),
eFlagRequiresTarget | eFlagProcessMustBePaused),
m_option_group (interpreter),
m_format_options (eFormatBytesWithASCII, 1, 8),
m_memory_options (),
@ -371,17 +371,11 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Target *target = exe_ctx.GetTargetPtr();
if (target == NULL)
{
result.AppendError("need at least a target to read memory");
result.SetStatus(eReturnStatusFailed);
return false;
}
// No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
Target *target = m_exe_ctx.GetTargetPtr();
const size_t argc = command.GetArgumentCount();
if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
{
result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
@ -496,7 +490,7 @@ protected:
}
ConstString lookup_type_name(type_str.c_str());
StackFrame *frame = exe_ctx.GetFramePtr();
StackFrame *frame = m_exe_ctx.GetFramePtr();
if (frame)
{
sc = frame->GetSymbolContext (eSymbolContextModule);
@ -603,7 +597,7 @@ protected:
}
if (argc > 0)
addr = Args::StringToAddress(&exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
if (addr == LLDB_INVALID_ADDRESS)
{
@ -615,7 +609,7 @@ protected:
if (argc == 2)
{
lldb::addr_t end_addr = Args::StringToAddress(&exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
if (end_addr == LLDB_INVALID_ADDRESS)
{
result.AppendError("invalid end address expression.");
@ -742,7 +736,7 @@ protected:
}
ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
if (clang_ast_type.GetOpaqueQualType())
{
for (uint32_t i = 0; i<item_count; ++i)
@ -922,7 +916,7 @@ public:
"memory write",
"Write to the memory of the process being debugged.",
NULL,
eFlagProcessMustBeLaunched),
eFlagRequiresProcess | eFlagProcessMustBeLaunched),
m_option_group (interpreter),
m_format_options (eFormatBytes, 1, UINT64_MAX),
m_memory_options ()
@ -999,14 +993,8 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Process *process = exe_ctx.GetProcessPtr();
if (process == NULL)
{
result.AppendError("need a process to read memory");
result.SetStatus(eReturnStatusFailed);
return false;
}
// No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
Process *process = m_exe_ctx.GetProcessPtr();
const size_t argc = command.GetArgumentCount();
@ -1034,7 +1022,7 @@ protected:
size_t item_byte_size = byte_size_value.GetCurrentValue();
Error error;
lldb::addr_t addr = Args::StringToAddress (&exe_ctx,
lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
command.GetArgumentAtIndex(0),
LLDB_INVALID_ADDRESS,
&error);

View File

@ -357,11 +357,11 @@ class CommandObjectPlatformProcessLaunch : public CommandObjectParsed
{
public:
CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
CommandObjectParsed (interpreter,
"platform process launch",
"Launch a new process on a remote platform.",
"platform process launch program",
0),
eFlagRequiresTarget | eFlagTryTargetAPILock),
m_options (interpreter)
{
}
@ -387,14 +387,7 @@ protected:
{
Error error;
const uint32_t argc = args.GetArgumentCount();
Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
if (target == NULL)
{
result.AppendError ("invalid target, create a debug target using the 'target create' command");
result.SetStatus (eReturnStatusFailed);
return false;
}
Target *target = m_exe_ctx.GetTargetPtr();
Module *exe_module = target->GetExecutableModulePointer();
if (exe_module)
{

View File

@ -46,7 +46,8 @@ public:
CommandObjectParsed (interpreter,
"process launch",
"Launch the executable in the debugger.",
NULL),
NULL,
eFlagRequiresTarget),
m_options (interpreter)
{
CommandArgumentEntry arg;
@ -111,13 +112,6 @@ protected:
Debugger &debugger = m_interpreter.GetDebugger();
Target *target = debugger.GetSelectedTarget().get();
Error error;
if (target == NULL)
{
result.AppendError ("invalid target, create a debug target using the 'target create' command");
result.SetStatus (eReturnStatusFailed);
return false;
}
// If our listener is NULL, users aren't allows to launch
char filename[PATH_MAX];
const Module *exe_module = target->GetExecutableModulePointer();
@ -130,7 +124,7 @@ protected:
}
StateType state = eStateInvalid;
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process)
{
state = process->GetState();
@ -505,7 +499,7 @@ protected:
// and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop
// ourselves here.
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
StateType state = eStateInvalid;
if (process)
{
@ -686,7 +680,10 @@ public:
"process continue",
"Continue execution of all threads in the current process.",
"process continue",
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_options(interpreter)
{
}
@ -754,19 +751,10 @@ protected:
};
bool
DoExecute (Args& command,
CommandReturnObject &result)
DoExecute (Args& command, CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
bool synchronous_execution = m_interpreter.GetSynchronous ();
if (process == NULL)
{
result.AppendError ("no process to continue");
result.SetStatus (eReturnStatusFailed);
return false;
}
StateType state = process->GetState();
if (state == eStateStopped)
{
@ -878,6 +866,8 @@ public:
"process detach",
"Detach from the current process being debugged.",
"process detach",
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched)
{
}
@ -888,17 +878,9 @@ public:
protected:
bool
DoExecute (Args& command,
CommandReturnObject &result)
DoExecute (Args& command, CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
if (process == NULL)
{
result.AppendError ("must have a valid process in order to detach");
result.SetStatus (eReturnStatusFailed);
return false;
}
Process *process = m_exe_ctx.GetProcessPtr();
result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
Error error (process->Detach());
if (error.Success())
@ -1008,7 +990,7 @@ protected:
TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
Error error;
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process)
{
if (process->IsAlive())
@ -1112,7 +1094,7 @@ public:
virtual CommandObject *
GetProxyCommandObject()
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process)
return process->GetPluginCommandObject();
return NULL;
@ -1134,7 +1116,10 @@ public:
"process load",
"Load a shared library into the current process.",
"process load <filename> [<filename> ...]",
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused )
{
}
@ -1147,13 +1132,7 @@ protected:
DoExecute (Args& command,
CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
if (process == NULL)
{
result.AppendError ("must have a valid process in order to load a shared library");
result.SetStatus (eReturnStatusFailed);
return false;
}
Process *process = m_exe_ctx.GetProcessPtr();
const uint32_t argc = command.GetArgumentCount();
@ -1194,7 +1173,10 @@ public:
"process unload",
"Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
"process unload <index>",
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused )
{
}
@ -1207,13 +1189,7 @@ protected:
DoExecute (Args& command,
CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
if (process == NULL)
{
result.AppendError ("must have a valid process in order to load a shared library");
result.SetStatus (eReturnStatusFailed);
return false;
}
Process *process = m_exe_ctx.GetProcessPtr();
const uint32_t argc = command.GetArgumentCount();
@ -1260,7 +1236,8 @@ public:
CommandObjectParsed (interpreter,
"process signal",
"Send a UNIX signal to the current process being debugged.",
NULL)
NULL,
eFlagRequiresProcess | eFlagTryTargetAPILock)
{
CommandArgumentEntry arg;
CommandArgumentData signal_arg;
@ -1285,13 +1262,7 @@ protected:
DoExecute (Args& command,
CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
if (process == NULL)
{
result.AppendError ("no process to signal");
result.SetStatus (eReturnStatusFailed);
return false;
}
Process *process = m_exe_ctx.GetProcessPtr();
if (command.GetArgumentCount() == 1)
{
@ -1348,6 +1319,8 @@ public:
"process interrupt",
"Interrupt the current process being debugged.",
"process interrupt",
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched)
{
}
@ -1361,7 +1334,7 @@ protected:
DoExecute (Args& command,
CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process == NULL)
{
result.AppendError ("no process to halt");
@ -1411,6 +1384,8 @@ public:
"process kill",
"Terminate the current process being debugged.",
"process kill",
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched)
{
}
@ -1424,7 +1399,7 @@ protected:
DoExecute (Args& command,
CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process == NULL)
{
result.AppendError ("no process to kill");
@ -1469,7 +1444,7 @@ public:
"process status",
"Show the current status and location of executing process.",
"process status",
0)
eFlagRequiresProcess | eFlagTryTargetAPILock)
{
}
@ -1483,27 +1458,18 @@ public:
{
Stream &strm = result.GetOutputStream();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Process *process = exe_ctx.GetProcessPtr();
if (process)
{
const bool only_threads_with_stop_reason = true;
const uint32_t start_frame = 0;
const uint32_t num_frames = 1;
const uint32_t num_frames_with_source = 1;
process->GetStatus(strm);
process->GetThreadStatus (strm,
only_threads_with_stop_reason,
start_frame,
num_frames,
num_frames_with_source);
}
else
{
result.AppendError ("No process.");
result.SetStatus (eReturnStatusFailed);
}
// No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
Process *process = m_exe_ctx.GetProcessPtr();
const bool only_threads_with_stop_reason = true;
const uint32_t start_frame = 0;
const uint32_t num_frames = 1;
const uint32_t num_frames_with_source = 1;
process->GetStatus(strm);
process->GetThreadStatus (strm,
only_threads_with_stop_reason,
start_frame,
num_frames,
num_frames_with_source);
return result.Succeeded();
}
};

View File

@ -45,7 +45,10 @@ public:
"register read",
"Dump the contents of one or more register values from the current frame. If no register is specified, dumps them all.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
eFlagRequiresFrame |
eFlagRequiresRegContext |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_option_group (interpreter),
m_format_options (eFormatDefault),
m_command_options ()
@ -165,88 +168,79 @@ protected:
DoExecute (Args& command, CommandReturnObject &result)
{
Stream &strm = result.GetOutputStream();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
if (reg_ctx)
const RegisterInfo *reg_info = NULL;
if (command.GetArgumentCount() == 0)
{
const RegisterInfo *reg_info = NULL;
if (command.GetArgumentCount() == 0)
uint32_t set_idx;
uint32_t num_register_sets = 1;
const uint32_t set_array_size = m_command_options.set_indexes.GetSize();
if (set_array_size > 0)
{
uint32_t set_idx;
uint32_t num_register_sets = 1;
const uint32_t set_array_size = m_command_options.set_indexes.GetSize();
if (set_array_size > 0)
for (uint32_t i=0; i<set_array_size; ++i)
{
for (uint32_t i=0; i<set_array_size; ++i)
set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
if (set_idx != UINT32_MAX)
{
set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
if (set_idx != UINT32_MAX)
if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
{
if (!DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx))
{
result.AppendErrorWithFormat ("invalid register set index: %u\n", set_idx);
result.SetStatus (eReturnStatusFailed);
break;
}
}
else
{
result.AppendError ("invalid register set index\n");
result.AppendErrorWithFormat ("invalid register set index: %u\n", set_idx);
result.SetStatus (eReturnStatusFailed);
break;
}
}
}
else
{
if (m_command_options.dump_all_sets)
num_register_sets = reg_ctx->GetRegisterSetCount();
for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
else
{
// When dump_all_sets option is set, dump primitive as well as derived registers.
DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
result.AppendError ("invalid register set index\n");
result.SetStatus (eReturnStatusFailed);
break;
}
}
}
else
{
if (m_command_options.dump_all_sets)
{
result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
result.SetStatus (eReturnStatusFailed);
}
else if (m_command_options.set_indexes.GetSize() > 0)
{
result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
result.SetStatus (eReturnStatusFailed);
}
else
{
const char *arg_cstr;
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
{
reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
num_register_sets = reg_ctx->GetRegisterSetCount();
if (reg_info)
{
if (!DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
strm.Printf("%-12s = error: unavailable\n", reg_info->name);
}
else
{
result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
}
}
for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
{
// When dump_all_sets option is set, dump primitive as well as derived registers.
DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
}
}
}
else
{
result.AppendError ("no current frame");
result.SetStatus (eReturnStatusFailed);
if (m_command_options.dump_all_sets)
{
result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
result.SetStatus (eReturnStatusFailed);
}
else if (m_command_options.set_indexes.GetSize() > 0)
{
result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
result.SetStatus (eReturnStatusFailed);
}
else
{
const char *arg_cstr;
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
{
reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
if (reg_info)
{
if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
strm.Printf("%-12s = error: unavailable\n", reg_info->name);
}
else
{
result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
}
}
}
}
return result.Succeeded();
}
@ -366,7 +360,10 @@ public:
"register write",
"Modify a single register value.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
eFlagRequiresFrame |
eFlagRequiresRegContext |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused)
{
CommandArgumentEntry arg1;
CommandArgumentEntry arg2;
@ -402,65 +399,56 @@ protected:
DoExecute(Args& command, CommandReturnObject &result)
{
DataExtractor reg_data;
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
if (reg_ctx)
if (command.GetArgumentCount() != 2)
{
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_ctx->GetRegisterInfoByName(reg_name);
if (reg_info)
{
result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
RegisterValue reg_value;
Error error (reg_value.SetValueFromCString (reg_info, value_str));
if (error.Success())
{
if (reg_ctx->WriteRegister (reg_info, reg_value))
{
// Toss all frames and anything else in the thread
// after a register has been written.
m_exe_ctx.GetThreadRef().Flush();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
return true;
}
}
if (error.AsCString())
{
result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
reg_name,
value_str,
error.AsCString());
}
else
{
result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
reg_name,
value_str);
}
result.SetStatus (eReturnStatusFailed);
}
else
{
const char *reg_name = command.GetArgumentAtIndex(0);
const char *value_str = command.GetArgumentAtIndex(1);
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
if (reg_info)
{
RegisterValue reg_value;
Error error (reg_value.SetValueFromCString (reg_info, value_str));
if (error.Success())
{
if (reg_ctx->WriteRegister (reg_info, reg_value))
{
// Toss all frames and anything else in the thread
// after a register has been written.
exe_ctx.GetThreadRef().Flush();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
return true;
}
}
if (error.AsCString())
{
result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
reg_name,
value_str,
error.AsCString());
}
else
{
result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
reg_name,
value_str);
}
result.SetStatus (eReturnStatusFailed);
}
else
{
result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
result.SetStatus (eReturnStatusFailed);
}
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();
}
};

View File

@ -202,12 +202,10 @@ insert-before or insert-after.\n");
}
else
{
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
// Complete setting value
const char *setting_var_name = input.GetArgumentAtIndex(setting_var_idx);
Error error;
lldb::OptionValueSP value_sp (m_interpreter.GetDebugger().GetPropertyValue(&exe_ctx, setting_var_name, false, error));
lldb::OptionValueSP value_sp (m_interpreter.GetDebugger().GetPropertyValue(&m_exe_ctx, setting_var_name, false, error));
if (value_sp)
{
value_sp->AutoComplete (m_interpreter,
@ -256,7 +254,6 @@ protected:
StripLeadingSpaces(var_value_str);
std::string var_value_string = var_value_str.str();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Error error;
if (m_options.m_global)
{
@ -268,7 +265,7 @@ protected:
if (error.Success())
{
error = m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
error = m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
eVarSetOperationAssign,
var_name,
var_value_string.c_str());
@ -357,7 +354,6 @@ protected:
virtual bool
DoExecute (Args& args, CommandReturnObject &result)
{
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
result.SetStatus (eReturnStatusSuccessFinishResult);
const size_t argc = args.GetArgumentCount ();
@ -367,7 +363,7 @@ protected:
{
const char *property_path = args.GetArgumentAtIndex (i);
Error error(m_interpreter.GetDebugger().DumpPropertyValue (&exe_ctx, result.GetOutputStream(), property_path, OptionValue::eDumpGroupValue));
Error error(m_interpreter.GetDebugger().DumpPropertyValue (&m_exe_ctx, result.GetOutputStream(), property_path, OptionValue::eDumpGroupValue));
if (error.Success())
{
result.GetOutputStream().EOL();
@ -381,7 +377,7 @@ protected:
}
else
{
m_interpreter.GetDebugger().DumpAllPropertyValues (& exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue);
m_interpreter.GetDebugger().DumpAllPropertyValues (&m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue);
}
return result.Succeeded();
@ -450,7 +446,6 @@ protected:
virtual bool
DoExecute (Args& args, CommandReturnObject &result)
{
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
result.SetStatus (eReturnStatusSuccessFinishResult);
const bool will_modify = false;
@ -463,7 +458,7 @@ protected:
{
const char *property_path = args.GetArgumentAtIndex (i);
const Property *property = m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath (&exe_ctx, will_modify, property_path);
const Property *property = m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath (&m_exe_ctx, will_modify, property_path);
if (property)
{
@ -592,8 +587,7 @@ protected:
StripLeadingSpaces(var_value_str);
std::string var_value_string = var_value_str.str();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Error error (m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
Error error (m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
eVarSetOperationRemove,
var_name,
var_value_string.c_str()));
@ -719,8 +713,7 @@ protected:
StripLeadingSpaces(var_value_str);
std::string var_value_string = var_value_str.str();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Error error(m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
eVarSetOperationReplace,
var_name,
var_value_string.c_str()));
@ -853,8 +846,7 @@ protected:
StripLeadingSpaces(var_value_str);
std::string var_value_string = var_value_str.str();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Error error(m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
eVarSetOperationInsertBefore,
var_name,
var_value_string.c_str()));
@ -982,8 +974,7 @@ protected:
StripLeadingSpaces(var_value_str);
std::string var_value_string = var_value_str.str();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Error error(m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
eVarSetOperationInsertAfter,
var_name,
var_value_string.c_str()));
@ -1102,8 +1093,7 @@ protected:
StripLeadingSpaces(var_value_str);
std::string var_value_string = var_value_str.str();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Error error(m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
eVarSetOperationAppend,
var_name,
var_value_string.c_str()));
@ -1196,8 +1186,7 @@ protected:
return false;
}
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Error error (m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
Error error (m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
eVarSetOperationClear,
var_name,
NULL));

View File

@ -250,7 +250,8 @@ public:
CommandObjectParsed (interpreter,
"source list",
"Display source code (as specified) based on the current executable's debug info.",
NULL),
NULL,
eFlagRequiresTarget),
m_options (interpreter)
{
}
@ -307,18 +308,7 @@ protected:
return false;
}
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Target *target = exe_ctx.GetTargetPtr();
if (target == NULL)
target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
{
result.AppendError ("invalid target, create a debug target using the 'target create' command");
result.SetStatus (eReturnStatusFailed);
return false;
}
Target *target = m_exe_ctx.GetTargetPtr();
SymbolContextList sc_list;
if (!m_options.symbol_name.empty())
@ -455,7 +445,7 @@ protected:
{
const bool show_inlines = true;
m_breakpoint_locations.Reset (start_file, 0, show_inlines);
SearchFilter target_search_filter (exe_ctx.GetTargetSP());
SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
target_search_filter.Search (m_breakpoint_locations);
}
else
@ -556,7 +546,7 @@ protected:
bool show_module = true;
bool show_inlined_frames = true;
sc.DumpStopContext(&result.GetOutputStream(),
exe_ctx.GetBestExecutionContextScope(),
m_exe_ctx.GetBestExecutionContextScope(),
sc.line_entry.range.GetBaseAddress(),
show_fullpaths,
show_module,

View File

@ -600,7 +600,7 @@ public:
"target variable",
"Read global variable(s) prior to, or while running your binary.",
NULL,
0),
eFlagRequiresTarget),
m_option_group (interpreter),
m_option_variable (false), // Don't include frame options
m_option_format (eFormatDefault),
@ -769,188 +769,66 @@ protected:
virtual bool
DoExecute (Args& args, CommandReturnObject &result)
{
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Target *target = exe_ctx.GetTargetPtr();
if (target)
Target *target = m_exe_ctx.GetTargetPtr();
const size_t argc = args.GetArgumentCount();
Stream &s = result.GetOutputStream();
if (argc > 0)
{
const size_t argc = args.GetArgumentCount();
Stream &s = result.GetOutputStream();
if (argc > 0)
for (size_t idx = 0; idx < argc; ++idx)
{
VariableList variable_list;
ValueObjectList valobj_list;
for (size_t idx = 0; idx < argc; ++idx)
const char *arg = args.GetArgumentAtIndex(idx);
uint32_t matches = 0;
bool use_var_name = false;
if (m_option_variable.use_regex)
{
VariableList variable_list;
ValueObjectList valobj_list;
const char *arg = args.GetArgumentAtIndex(idx);
uint32_t matches = 0;
bool use_var_name = false;
if (m_option_variable.use_regex)
RegularExpression regex(arg);
if (!regex.IsValid ())
{
RegularExpression regex(arg);
if (!regex.IsValid ())
{
result.GetErrorStream().Printf ("error: invalid regular expression: '%s'\n", arg);
result.SetStatus (eReturnStatusFailed);
return false;
}
use_var_name = true;
matches = target->GetImages().FindGlobalVariables (regex,
true,
UINT32_MAX,
variable_list);
}
else
{
Error error (Variable::GetValuesForVariableExpressionPath (arg,
exe_ctx.GetBestExecutionContextScope(),
GetVariableCallback,
target,
variable_list,
valobj_list));
matches = variable_list.GetSize();
}
if (matches == 0)
{
result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", arg);
result.GetErrorStream().Printf ("error: invalid regular expression: '%s'\n", arg);
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
for (uint32_t global_idx=0; global_idx<matches; ++global_idx)
{
VariableSP var_sp (variable_list.GetVariableAtIndex(global_idx));
if (var_sp)
{
ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(global_idx));
if (!valobj_sp)
valobj_sp = ValueObjectVariable::Create (exe_ctx.GetBestExecutionContextScope(), var_sp);
if (valobj_sp)
DumpValueObject (s, var_sp, valobj_sp, use_var_name ? var_sp->GetName().GetCString() : arg);
}
}
}
}
}
else
{
const FileSpecList &compile_units = m_option_compile_units.GetOptionValue().GetCurrentValue();
const FileSpecList &shlibs = m_option_shared_libraries.GetOptionValue().GetCurrentValue();
SymbolContextList sc_list;
const size_t num_compile_units = compile_units.GetSize();
const size_t num_shlibs = shlibs.GetSize();
if (num_compile_units == 0 && num_shlibs == 0)
{
bool success = false;
StackFrame *frame = exe_ctx.GetFramePtr();
CompileUnit *comp_unit = NULL;
if (frame)
{
SymbolContext sc = frame->GetSymbolContext (eSymbolContextCompUnit);
if (sc.comp_unit)
{
const bool can_create = true;
VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create));
if (comp_unit_varlist_sp)
{
size_t count = comp_unit_varlist_sp->GetSize();
if (count > 0)
{
DumpGlobalVariableList(exe_ctx, sc, *comp_unit_varlist_sp, s);
success = true;
}
}
}
}
if (!success)
{
if (frame)
{
if (comp_unit)
result.AppendErrorWithFormat ("no global variables in current compile unit: %s/%s\n",
comp_unit->GetDirectory().GetCString(),
comp_unit->GetFilename().GetCString());
else
result.AppendErrorWithFormat ("no debug information for frame %u\n", frame->GetFrameIndex());
}
else
result.AppendError ("'target variable' takes one or more global variable names as arguments\n");
result.SetStatus (eReturnStatusFailed);
}
use_var_name = true;
matches = target->GetImages().FindGlobalVariables (regex,
true,
UINT32_MAX,
variable_list);
}
else
{
SymbolContextList sc_list;
const bool append = true;
// We have one or more compile unit or shlib
if (num_shlibs > 0)
Error error (Variable::GetValuesForVariableExpressionPath (arg,
m_exe_ctx.GetBestExecutionContextScope(),
GetVariableCallback,
target,
variable_list,
valobj_list));
matches = variable_list.GetSize();
}
if (matches == 0)
{
result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", arg);
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
for (uint32_t global_idx=0; global_idx<matches; ++global_idx)
{
for (size_t shlib_idx=0; shlib_idx<num_shlibs; ++shlib_idx)
VariableSP var_sp (variable_list.GetVariableAtIndex(global_idx));
if (var_sp)
{
const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
ModuleSpec module_spec (module_file);
ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(global_idx));
if (!valobj_sp)
valobj_sp = ValueObjectVariable::Create (m_exe_ctx.GetBestExecutionContextScope(), var_sp);
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
if (module_sp)
{
if (num_compile_units > 0)
{
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
module_sp->FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
}
else
{
SymbolContext sc;
sc.module_sp = module_sp;
sc_list.Append(sc);
}
}
else
{
// Didn't find matching shlib/module in target...
result.AppendErrorWithFormat ("target doesn't contain the specified shared library: %s%s%s\n",
module_file.GetDirectory().GetCString(),
module_file.GetDirectory() ? "/" : "",
module_file.GetFilename().GetCString());
}
}
}
else
{
// No shared libraries, we just want to find globals for the compile units files that were specified
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
target->GetImages().FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
}
const uint32_t num_scs = sc_list.GetSize();
if (num_scs > 0)
{
SymbolContext sc;
for (uint32_t sc_idx=0; sc_idx<num_scs; ++sc_idx)
{
if (sc_list.GetContextAtIndex(sc_idx, sc))
{
if (sc.comp_unit)
{
const bool can_create = true;
VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create));
if (comp_unit_varlist_sp)
DumpGlobalVariableList(exe_ctx, sc, *comp_unit_varlist_sp, s);
}
else if (sc.module_sp)
{
// Get all global variables for this module
lldb_private::RegularExpression all_globals_regex("."); // Any global with at least one character
VariableList variable_list;
sc.module_sp->FindGlobalVariables(all_globals_regex, append, UINT32_MAX, variable_list);
DumpGlobalVariableList(exe_ctx, sc, variable_list, s);
}
}
if (valobj_sp)
DumpValueObject (s, var_sp, valobj_sp, use_var_name ? var_sp->GetName().GetCString() : arg);
}
}
}
@ -958,11 +836,123 @@ protected:
}
else
{
result.AppendError ("invalid target, create a debug target using the 'target create' command");
result.SetStatus (eReturnStatusFailed);
return false;
const FileSpecList &compile_units = m_option_compile_units.GetOptionValue().GetCurrentValue();
const FileSpecList &shlibs = m_option_shared_libraries.GetOptionValue().GetCurrentValue();
SymbolContextList sc_list;
const size_t num_compile_units = compile_units.GetSize();
const size_t num_shlibs = shlibs.GetSize();
if (num_compile_units == 0 && num_shlibs == 0)
{
bool success = false;
StackFrame *frame = m_exe_ctx.GetFramePtr();
CompileUnit *comp_unit = NULL;
if (frame)
{
SymbolContext sc = frame->GetSymbolContext (eSymbolContextCompUnit);
if (sc.comp_unit)
{
const bool can_create = true;
VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create));
if (comp_unit_varlist_sp)
{
size_t count = comp_unit_varlist_sp->GetSize();
if (count > 0)
{
DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
success = true;
}
}
}
}
if (!success)
{
if (frame)
{
if (comp_unit)
result.AppendErrorWithFormat ("no global variables in current compile unit: %s/%s\n",
comp_unit->GetDirectory().GetCString(),
comp_unit->GetFilename().GetCString());
else
result.AppendErrorWithFormat ("no debug information for frame %u\n", frame->GetFrameIndex());
}
else
result.AppendError ("'target variable' takes one or more global variable names as arguments\n");
result.SetStatus (eReturnStatusFailed);
}
}
else
{
SymbolContextList sc_list;
const bool append = true;
// We have one or more compile unit or shlib
if (num_shlibs > 0)
{
for (size_t shlib_idx=0; shlib_idx<num_shlibs; ++shlib_idx)
{
const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
ModuleSpec module_spec (module_file);
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
if (module_sp)
{
if (num_compile_units > 0)
{
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
module_sp->FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
}
else
{
SymbolContext sc;
sc.module_sp = module_sp;
sc_list.Append(sc);
}
}
else
{
// Didn't find matching shlib/module in target...
result.AppendErrorWithFormat ("target doesn't contain the specified shared library: %s%s%s\n",
module_file.GetDirectory().GetCString(),
module_file.GetDirectory() ? "/" : "",
module_file.GetFilename().GetCString());
}
}
}
else
{
// No shared libraries, we just want to find globals for the compile units files that were specified
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
target->GetImages().FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
}
const uint32_t num_scs = sc_list.GetSize();
if (num_scs > 0)
{
SymbolContext sc;
for (uint32_t sc_idx=0; sc_idx<num_scs; ++sc_idx)
{
if (sc_list.GetContextAtIndex(sc_idx, sc))
{
if (sc.comp_unit)
{
const bool can_create = true;
VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create));
if (comp_unit_varlist_sp)
DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
}
else if (sc.module_sp)
{
// Get all global variables for this module
lldb_private::RegularExpression all_globals_regex("."); // Any global with at least one character
VariableList variable_list;
sc.module_sp->FindGlobalVariables(all_globals_regex, append, UINT32_MAX, variable_list);
DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
}
}
}
}
}
}
if (m_interpreter.TruncationWarningNecessary())
{
result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
@ -1997,10 +1987,11 @@ class CommandObjectTargetModulesSourceFileAutoComplete : public CommandObjectPar
public:
CommandObjectTargetModulesSourceFileAutoComplete (CommandInterpreter &interpreter,
const char *name,
const char *help,
const char *syntax) :
CommandObjectParsed (interpreter, name, help, syntax)
const char *name,
const char *help,
const char *syntax,
uint32_t flags) :
CommandObjectParsed (interpreter, name, help, syntax, flags)
{
CommandArgumentEntry arg;
CommandArgumentData source_file_arg;
@ -2461,9 +2452,10 @@ class CommandObjectTargetModulesDumpLineTable : public CommandObjectTargetModule
public:
CommandObjectTargetModulesDumpLineTable (CommandInterpreter &interpreter) :
CommandObjectTargetModulesSourceFileAutoComplete (interpreter,
"target modules dump line-table",
"Dump the debug symbol file for one or more target modules.",
NULL)
"target modules dump line-table",
"Dump the debug symbol file for one or more target modules.",
NULL,
eFlagRequiresTarget)
{
}
@ -2477,65 +2469,55 @@ protected:
DoExecute (Args& command,
CommandReturnObject &result)
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (target == NULL)
Target *target = m_exe_ctx.GetTargetPtr();
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.AppendError ("invalid target, create a debug target using the 'target create' command");
result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
result.SetStatus (eReturnStatusFailed);
return false;
}
else
{
ExecutionContext exe_ctx(m_interpreter.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)
// 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)
{
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, false);
const ModuleList &target_modules = target->GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
const uint32_t num_modules = target_modules.GetSize();
if (num_modules > 0)
{
FileSpec file_spec(arg_cstr, false);
const ModuleList &target_modules = target->GetImages();
Mutex::Locker modules_locker(target_modules.GetMutex());
const uint32_t num_modules = target_modules.GetSize();
if (num_modules > 0)
uint32_t num_dumped = 0;
for (uint32_t i = 0; i<num_modules; ++i)
{
uint32_t num_dumped = 0;
for (uint32_t i = 0; i<num_modules; ++i)
{
if (DumpCompileUnitLineTable (m_interpreter,
result.GetOutputStream(),
target_modules.GetModulePointerAtIndexUnlocked(i),
file_spec,
exe_ctx.GetProcessPtr() && exe_ctx.GetProcessRef().IsAlive()))
num_dumped++;
}
if (num_dumped == 0)
result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
else
total_num_dumped += num_dumped;
if (DumpCompileUnitLineTable (m_interpreter,
result.GetOutputStream(),
target_modules.GetModulePointerAtIndexUnlocked(i),
file_spec,
m_exe_ctx.GetProcessPtr() && m_exe_ctx.GetProcessRef().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);
}
}
if (total_num_dumped > 0)
result.SetStatus (eReturnStatusSuccessFinishResult);
else
{
result.AppendError ("no source filenames matched any command arguments");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
}
@ -3475,10 +3457,10 @@ public:
public:
CommandOptions (CommandInterpreter &interpreter) :
Options(interpreter),
m_type(eLookupTypeInvalid),
m_str(),
m_addr(LLDB_INVALID_ADDRESS)
Options(interpreter),
m_type(eLookupTypeInvalid),
m_str(),
m_addr(LLDB_INVALID_ADDRESS)
{
}
@ -3541,7 +3523,11 @@ public:
CommandObjectParsed (interpreter,
"target modules show-unwind",
"Show synthesized unwind instructions for a function.",
NULL),
NULL,
eFlagRequiresTarget |
eFlagRequiresProcess |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_options (interpreter)
{
}
@ -3563,16 +3549,8 @@ protected:
DoExecute (Args& command,
CommandReturnObject &result)
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
if (!target)
{
result.AppendError ("invalid target, create a debug target using the 'target create' command");
result.SetStatus (eReturnStatusFailed);
return false;
}
ExecutionContext exe_ctx = m_interpreter.GetDebugger().GetSelectedExecutionContext();
Process *process = exe_ctx.GetProcessPtr();
Target *target = m_exe_ctx.GetTargetPtr();
Process *process = m_exe_ctx.GetProcessPtr();
ABI *abi = NULL;
if (process)
abi = process->GetABI().get();
@ -3837,7 +3815,8 @@ public:
CommandObjectParsed (interpreter,
"target modules lookup",
"Look up information within executable and dependent shared library images.",
NULL),
NULL,
eFlagRequiresTarget),
m_options (interpreter)
{
CommandArgumentEntry arg;
@ -3881,9 +3860,7 @@ public:
break;
}
ExecutionContext exe_ctx = interpreter.GetDebugger().GetSelectedExecutionContext();
StackFrameSP frame = exe_ctx.GetFrameSP();
StackFrameSP frame = m_exe_ctx.GetFrameSP();
if (!frame)
return false;
@ -4375,198 +4352,190 @@ protected:
DoExecute (Args& args,
CommandReturnObject &result)
{
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Target *target = exe_ctx.GetTargetPtr();
Target *target = m_exe_ctx.GetTargetPtr();
result.SetStatus (eReturnStatusFailed);
if (target == NULL)
{
result.AppendError ("invalid target, create a debug target using the 'target create' command");
}
else
{
bool flush = false;
ModuleSpec module_spec;
const bool uuid_option_set = m_uuid_option_group.GetOptionValue().OptionWasSet();
const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
const bool frame_option_set = m_current_frame_option.GetOptionValue().OptionWasSet();
bool flush = false;
ModuleSpec module_spec;
const bool uuid_option_set = m_uuid_option_group.GetOptionValue().OptionWasSet();
const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
const bool frame_option_set = m_current_frame_option.GetOptionValue().OptionWasSet();
const size_t argc = args.GetArgumentCount();
if (argc == 0)
const size_t argc = args.GetArgumentCount();
if (argc == 0)
{
if (uuid_option_set || file_option_set || frame_option_set)
{
if (uuid_option_set || file_option_set || frame_option_set)
bool success = false;
bool error_set = false;
if (frame_option_set)
{
bool success = false;
bool error_set = false;
if (frame_option_set)
Process *process = m_exe_ctx.GetProcessPtr();
if (process)
{
Process *process = exe_ctx.GetProcessPtr();
if (process)
const StateType process_state = process->GetState();
if (StateIsStoppedState (process_state, true))
{
const StateType process_state = process->GetState();
if (StateIsStoppedState (process_state, true))
StackFrame *frame = m_exe_ctx.GetFramePtr();
if (frame)
{
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame)
ModuleSP frame_module_sp (frame->GetSymbolContext(eSymbolContextModule).module_sp);
if (frame_module_sp)
{
ModuleSP frame_module_sp (frame->GetSymbolContext(eSymbolContextModule).module_sp);
if (frame_module_sp)
if (frame_module_sp->GetPlatformFileSpec().Exists())
{
if (frame_module_sp->GetPlatformFileSpec().Exists())
{
module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
}
module_spec.GetUUID() = frame_module_sp->GetUUID();
success = module_spec.GetUUID().IsValid() || module_spec.GetFileSpec();
}
else
{
result.AppendError ("frame has no module");
error_set = true;
module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
}
module_spec.GetUUID() = frame_module_sp->GetUUID();
success = module_spec.GetUUID().IsValid() || module_spec.GetFileSpec();
}
else
{
result.AppendError ("invalid current frame");
result.AppendError ("frame has no module");
error_set = true;
}
}
else
{
result.AppendErrorWithFormat ("process is not stopped: %s", StateAsCString(process_state));
result.AppendError ("invalid current frame");
error_set = true;
}
}
else
{
result.AppendError ("a process must exist in order to use the --frame option");
result.AppendErrorWithFormat ("process is not stopped: %s", StateAsCString(process_state));
error_set = true;
}
}
else
{
if (uuid_option_set)
{
module_spec.GetUUID() = m_uuid_option_group.GetOptionValue().GetCurrentValue();
success |= module_spec.GetUUID().IsValid();
}
else if (file_option_set)
{
module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue();
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
if (module_sp)
{
module_spec.GetFileSpec() = module_sp->GetFileSpec();
module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
module_spec.GetUUID() = module_sp->GetUUID();
module_spec.GetArchitecture() = module_sp->GetArchitecture();
}
else
{
module_spec.GetArchitecture() = target->GetArchitecture();
}
success |= module_spec.GetFileSpec().Exists();
}
}
if (success)
{
if (Symbols::DownloadObjectAndSymbolFile (module_spec))
{
if (module_spec.GetSymbolFileSpec())
success = AddModuleSymbols (target, module_spec, flush, result);
}
}
if (!success && !error_set)
{
StreamString error_strm;
if (uuid_option_set)
{
error_strm.PutCString("unable to find debug symbols for UUID ");
module_spec.GetUUID().Dump (&error_strm);
}
else if (file_option_set)
{
error_strm.PutCString("unable to find debug symbols for the executable file ");
error_strm << module_spec.GetFileSpec();
}
else if (frame_option_set)
{
error_strm.PutCString("unable to find debug symbols for the current frame");
}
result.AppendError (error_strm.GetData());
result.AppendError ("a process must exist in order to use the --frame option");
error_set = true;
}
}
else
{
result.AppendError ("one or more symbol file paths must be specified, or options must be specified");
if (uuid_option_set)
{
module_spec.GetUUID() = m_uuid_option_group.GetOptionValue().GetCurrentValue();
success |= module_spec.GetUUID().IsValid();
}
else if (file_option_set)
{
module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue();
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
if (module_sp)
{
module_spec.GetFileSpec() = module_sp->GetFileSpec();
module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
module_spec.GetUUID() = module_sp->GetUUID();
module_spec.GetArchitecture() = module_sp->GetArchitecture();
}
else
{
module_spec.GetArchitecture() = target->GetArchitecture();
}
success |= module_spec.GetFileSpec().Exists();
}
}
if (success)
{
if (Symbols::DownloadObjectAndSymbolFile (module_spec))
{
if (module_spec.GetSymbolFileSpec())
success = AddModuleSymbols (target, module_spec, flush, result);
}
}
if (!success && !error_set)
{
StreamString error_strm;
if (uuid_option_set)
{
error_strm.PutCString("unable to find debug symbols for UUID ");
module_spec.GetUUID().Dump (&error_strm);
}
else if (file_option_set)
{
error_strm.PutCString("unable to find debug symbols for the executable file ");
error_strm << module_spec.GetFileSpec();
}
else if (frame_option_set)
{
error_strm.PutCString("unable to find debug symbols for the current frame");
}
result.AppendError (error_strm.GetData());
}
}
else
{
if (uuid_option_set)
{
result.AppendError ("specify either one or more paths to symbol files or use the --uuid option without arguments");
}
else if (file_option_set)
{
result.AppendError ("specify either one or more paths to symbol files or use the --file option without arguments");
}
else if (frame_option_set)
{
result.AppendError ("specify either one or more paths to symbol files or use the --frame option without arguments");
}
else
{
PlatformSP platform_sp (target->GetPlatform());
result.AppendError ("one or more symbol file paths must be specified, or options must be specified");
}
}
else
{
if (uuid_option_set)
{
result.AppendError ("specify either one or more paths to symbol files or use the --uuid option without arguments");
}
else if (file_option_set)
{
result.AppendError ("specify either one or more paths to symbol files or use the --file option without arguments");
}
else if (frame_option_set)
{
result.AppendError ("specify either one or more paths to symbol files or use the --frame option without arguments");
}
else
{
PlatformSP platform_sp (target->GetPlatform());
for (size_t i=0; i<argc; ++i)
for (size_t i=0; i<argc; ++i)
{
const char *symfile_path = args.GetArgumentAtIndex(i);
if (symfile_path)
{
const char *symfile_path = args.GetArgumentAtIndex(i);
if (symfile_path)
module_spec.GetSymbolFileSpec().SetFile(symfile_path, true);
if (platform_sp)
{
module_spec.GetSymbolFileSpec().SetFile(symfile_path, true);
if (platform_sp)
{
FileSpec symfile_spec;
if (platform_sp->ResolveSymbolFile(*target, module_spec, symfile_spec).Success())
module_spec.GetSymbolFileSpec() = symfile_spec;
}
ArchSpec arch;
bool symfile_exists = module_spec.GetSymbolFileSpec().Exists();
FileSpec symfile_spec;
if (platform_sp->ResolveSymbolFile(*target, module_spec, symfile_spec).Success())
module_spec.GetSymbolFileSpec() = symfile_spec;
}
ArchSpec arch;
bool symfile_exists = module_spec.GetSymbolFileSpec().Exists();
if (symfile_exists)
{
if (!AddModuleSymbols (target, module_spec, flush, result))
break;
}
else
{
char resolved_symfile_path[PATH_MAX];
if (module_spec.GetSymbolFileSpec().GetPath (resolved_symfile_path, sizeof(resolved_symfile_path)))
{
if (strcmp (resolved_symfile_path, symfile_path) != 0)
{
result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", symfile_path, resolved_symfile_path);
break;
}
}
result.AppendErrorWithFormat ("invalid module path '%s'\n", symfile_path);
if (symfile_exists)
{
if (!AddModuleSymbols (target, module_spec, flush, result))
break;
}
else
{
char resolved_symfile_path[PATH_MAX];
if (module_spec.GetSymbolFileSpec().GetPath (resolved_symfile_path, sizeof(resolved_symfile_path)))
{
if (strcmp (resolved_symfile_path, symfile_path) != 0)
{
result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", symfile_path, resolved_symfile_path);
break;
}
}
result.AppendErrorWithFormat ("invalid module path '%s'\n", symfile_path);
break;
}
}
}
}
}
if (flush)
{
Process *process = exe_ctx.GetProcessPtr();
if (process)
process->Flush();
}
if (flush)
{
Process *process = m_exe_ctx.GetProcessPtr();
if (process)
process->Flush();
}
return result.Succeeded();
}

View File

@ -125,10 +125,14 @@ public:
CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
CommandObjectParsed (interpreter,
"thread backtrace",
"Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
"thread backtrace",
"Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.",
NULL,
eFlagRequiresProcess |
eFlagRequiresThread |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_options(interpreter)
{
CommandArgumentEntry arg;
@ -166,28 +170,19 @@ protected:
const uint32_t num_frames_with_source = 0;
if (command.GetArgumentCount() == 0)
{
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Thread *thread = exe_ctx.GetThreadPtr();
if (thread)
Thread *thread = m_exe_ctx.GetThreadPtr();
// Thread::GetStatus() returns the number of frames shown.
if (thread->GetStatus (strm,
m_options.m_start,
m_options.m_count,
num_frames_with_source))
{
// Thread::GetStatus() returns the number of frames shown.
if (thread->GetStatus (strm,
m_options.m_start,
m_options.m_count,
num_frames_with_source))
{
result.SetStatus (eReturnStatusSuccessFinishResult);
}
}
else
{
result.AppendError ("invalid thread");
result.SetStatus (eReturnStatusFailed);
result.SetStatus (eReturnStatusSuccessFinishResult);
}
}
else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
Mutex::Locker locker (process->GetThreadList().GetMutex());
uint32_t num_threads = process->GetThreadList().GetSize();
for (uint32_t i = 0; i < num_threads; i++)
@ -211,7 +206,7 @@ protected:
else
{
uint32_t num_args = command.GetArgumentCount();
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
Mutex::Locker locker (process->GetThreadList().GetMutex());
std::vector<ThreadSP> thread_sps;
@ -370,10 +365,14 @@ public:
const char *name,
const char *help,
const char *syntax,
uint32_t flags,
StepType step_type,
StepScope step_scope) :
CommandObjectParsed (interpreter, name, help, syntax, flags),
CommandObjectParsed (interpreter, name, help, syntax,
eFlagRequiresProcess |
eFlagRequiresThread |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_step_type (step_type),
m_step_scope (step_scope),
m_options (interpreter)
@ -408,169 +407,160 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
bool synchronous_execution = m_interpreter.GetSynchronous();
if (process == NULL)
const uint32_t num_threads = process->GetThreadList().GetSize();
Thread *thread = NULL;
if (command.GetArgumentCount() == 0)
{
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().GetSelectedThread().get();
if (thread == NULL)
{
thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL)
{
result.AppendError ("no selected 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, 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 if (m_options.m_run_mode == eOnlyDuringStepping)
{
if (m_step_type == eStepTypeOut)
bool_stop_other_threads = false;
else
bool_stop_other_threads = true;
}
else
bool_stop_other_threads = true;
ThreadPlan *new_plan = NULL;
if (m_step_type == eStepTypeInto)
{
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame->HasDebugInformation ())
{
new_plan = thread->QueueThreadPlanForStepInRange (abort_other_plans,
frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
frame->GetSymbolContext(eSymbolContextEverything),
m_options.m_step_in_target.c_str(),
stop_other_threads,
m_options.m_avoid_no_debug);
if (new_plan && !m_options.m_avoid_regexp.empty())
{
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
}
}
else
new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
}
else if (m_step_type == eStepTypeOver)
{
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame->HasDebugInformation())
new_plan = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
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);
}
else if (m_step_type == eStepTypeTrace)
{
new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
}
else if (m_step_type == eStepTypeTraceOver)
{
new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
}
else if (m_step_type == eStepTypeOut)
{
new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
NULL,
false,
bool_stop_other_threads,
eVoteYes,
eVoteNoOpinion,
thread->GetSelectedFrameIndex());
}
else
{
result.AppendError ("step type is not supported");
result.AppendError ("no selected thread in process");
result.SetStatus (eReturnStatusFailed);
return false;
}
// If we got a new plan, then set it to be a master plan (User level Plans should be master plans
// so that they can be interruptible). Then resume the process.
if (new_plan != NULL)
}
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)
{
new_plan->SetIsMasterPlan (true);
new_plan->SetOkayToDiscard (false);
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, num_threads);
result.SetStatus (eReturnStatusFailed);
return false;
}
}
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
process->Resume ();
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 if (m_options.m_run_mode == eOnlyDuringStepping)
{
if (m_step_type == eStepTypeOut)
bool_stop_other_threads = false;
else
bool_stop_other_threads = true;
}
else
bool_stop_other_threads = true;
if (synchronous_execution)
ThreadPlan *new_plan = NULL;
if (m_step_type == eStepTypeInto)
{
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame->HasDebugInformation ())
{
new_plan = thread->QueueThreadPlanForStepInRange (abort_other_plans,
frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
frame->GetSymbolContext(eSymbolContextEverything),
m_options.m_step_in_target.c_str(),
stop_other_threads,
m_options.m_avoid_no_debug);
if (new_plan && !m_options.m_avoid_regexp.empty())
{
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().SetSelectedThreadByID (thread->GetID());
result.SetDidChangeProcessState (true);
result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
{
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
}
}
else
new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
}
else if (m_step_type == eStepTypeOver)
{
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
if (frame->HasDebugInformation())
new_plan = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
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);
}
else if (m_step_type == eStepTypeTrace)
{
new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
}
else if (m_step_type == eStepTypeTraceOver)
{
new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
}
else if (m_step_type == eStepTypeOut)
{
new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
NULL,
false,
bool_stop_other_threads,
eVoteYes,
eVoteNoOpinion,
thread->GetSelectedFrameIndex());
}
else
{
result.AppendError ("step type is not supported");
result.SetStatus (eReturnStatusFailed);
return false;
}
// If we got a new plan, then set it to be a master plan (User level Plans should be master plans
// so that they can be interruptible). Then resume the process.
if (new_plan != NULL)
{
new_plan->SetIsMasterPlan (true);
new_plan->SetOkayToDiscard (false);
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
process->Resume ();
if (synchronous_execution)
{
result.AppendError ("Couldn't find thread plan to implement step type.");
result.SetStatus (eReturnStatusFailed);
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().SetSelectedThreadByID (thread->GetID());
result.SetDidChangeProcessState (true);
result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
result.SetStatus (eReturnStatusSuccessFinishNoResult);
}
else
{
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
}
}
else
{
result.AppendError ("Couldn't find thread plan to implement step type.");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded();
}
@ -622,7 +612,10 @@ public:
"thread continue",
"Continue execution of one or more threads in an active process.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
eFlagRequiresThread |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused)
{
CommandArgumentEntry arg;
CommandArgumentData thread_idx_arg;
@ -656,7 +649,7 @@ public:
return false;
}
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process == NULL)
{
result.AppendError ("no process exists. Cannot continue");
@ -902,7 +895,10 @@ public:
"thread until",
"Run the current or specified thread until it reaches a given line number or leaves the current function.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
eFlagRequiresThread |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_options (interpreter)
{
CommandArgumentEntry arg;
@ -946,7 +942,7 @@ protected:
return false;
}
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process == NULL)
{
result.AppendError ("need a valid process to step");
@ -1144,7 +1140,10 @@ public:
"thread select",
"Select a thread as the currently active thread.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused )
{
CommandArgumentEntry arg;
CommandArgumentData thread_idx_arg;
@ -1170,7 +1169,7 @@ protected:
virtual bool
DoExecute (Args& command, CommandReturnObject &result)
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Process *process = m_exe_ctx.GetProcessPtr();
if (process == NULL)
{
result.AppendError ("no process");
@ -1217,7 +1216,10 @@ public:
"thread list",
"Show a summary of all current threads in a process.",
"thread list",
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
eFlagRequiresProcess |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused )
{
}
@ -1231,26 +1233,17 @@ protected:
{
Stream &strm = result.GetOutputStream();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Process *process = exe_ctx.GetProcessPtr();
if (process)
{
const bool only_threads_with_stop_reason = false;
const uint32_t start_frame = 0;
const uint32_t num_frames = 0;
const uint32_t num_frames_with_source = 0;
process->GetStatus(strm);
process->GetThreadStatus (strm,
only_threads_with_stop_reason,
start_frame,
num_frames,
num_frames_with_source);
}
else
{
result.AppendError ("no current location or status available");
result.SetStatus (eReturnStatusFailed);
}
Process *process = m_exe_ctx.GetProcessPtr();
const bool only_threads_with_stop_reason = false;
const uint32_t start_frame = 0;
const uint32_t num_frames = 0;
const uint32_t num_frames_with_source = 0;
process->GetStatus(strm);
process->GetThreadStatus (strm,
only_threads_with_stop_reason,
start_frame,
num_frames,
num_frames_with_source);
return result.Succeeded();
}
};
@ -1263,7 +1256,10 @@ public:
"thread return",
"Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value.",
"thread return",
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
eFlagRequiresFrame |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused )
{
CommandArgumentEntry arg;
CommandArgumentData expression_arg;
@ -1293,18 +1289,9 @@ protected:
CommandReturnObject &result
)
{
// If there is a command string, pass it to the expression parser:
ExecutionContext exe_ctx = m_interpreter.GetExecutionContext();
if (!(exe_ctx.HasProcessScope() && exe_ctx.HasThreadScope() && exe_ctx.HasFrameScope()))
{
result.AppendError("Must have selected process, thread and frame for thread return.");
result.SetStatus (eReturnStatusFailed);
return false;
}
ValueObjectSP return_valobj_sp;
StackFrameSP frame_sp = exe_ctx.GetFrameSP();
StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
uint32_t frame_idx = frame_sp->GetFrameIndex();
if (frame_sp->IsInlined())
@ -1316,7 +1303,7 @@ protected:
if (command && command[0] != '\0')
{
Target *target = exe_ctx.GetTargetPtr();
Target *target = m_exe_ctx.GetTargetPtr();
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
@ -1340,7 +1327,7 @@ protected:
}
Error error;
ThreadSP thread_sp = exe_ctx.GetThreadSP();
ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
const bool broadcast = true;
error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
if (!error.Success())
@ -1377,7 +1364,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
"thread step-in",
"Source level single step in specified thread (current thread, if none specified).",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
eStepTypeInto,
eStepScopeSource)));
@ -1386,7 +1372,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
"thread step-out",
"Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
eStepTypeOut,
eStepScopeSource)));
@ -1395,7 +1380,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
"thread step-over",
"Source level single step in specified thread (current thread, if none specified), stepping over calls.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
eStepTypeOver,
eStepScopeSource)));
@ -1404,7 +1388,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
"thread step-inst",
"Single step one instruction in specified thread (current thread, if none specified).",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
eStepTypeTrace,
eStepScopeInstruction)));
@ -1413,7 +1396,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
"thread step-inst-over",
"Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
eStepTypeTraceOver,
eStepScopeInstruction)));
}

View File

@ -934,7 +934,10 @@ public:
"If watchpoint setting fails, consider disable/delete existing ones "
"to free up resources.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
eFlagRequiresFrame |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_option_group (interpreter),
m_option_watchpoint ()
{
@ -988,18 +991,10 @@ protected:
}
virtual bool
DoExecute (Args& command,
CommandReturnObject &result)
DoExecute (Args& command, CommandReturnObject &result)
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame == NULL)
{
result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
result.SetStatus (eReturnStatusFailed);
return false;
}
StackFrame *frame = m_exe_ctx.GetFramePtr();
// If no argument is present, issue an error message. There's no way to set a watchpoint.
if (command.GetArgumentCount() <= 0)
@ -1025,7 +1020,8 @@ protected:
Stream &output_stream = result.GetOutputStream();
// A simple watch variable gesture allows only one argument.
if (command.GetArgumentCount() != 1) {
if (command.GetArgumentCount() != 1)
{
result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n");
result.SetStatus(eReturnStatusFailed);
return false;
@ -1041,14 +1037,15 @@ protected:
var_sp,
error);
if (!valobj_sp) {
if (!valobj_sp)
{
// Not in the frame; let's check the globals.
VariableList variable_list;
ValueObjectList valobj_list;
Error error (Variable::GetValuesForVariableExpressionPath (command.GetArgumentAtIndex(0),
exe_ctx.GetBestExecutionContextScope(),
m_exe_ctx.GetBestExecutionContextScope(),
GetVariableCallback,
target,
variable_list,
@ -1060,17 +1057,21 @@ protected:
ClangASTType type;
if (valobj_sp) {
if (valobj_sp)
{
AddressType addr_type;
addr = valobj_sp->GetAddressOf(false, &addr_type);
if (addr_type == eAddressTypeLoad) {
if (addr_type == eAddressTypeLoad)
{
// We're in business.
// Find out the size of this variable.
size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize()
: m_option_watchpoint.watch_size;
}
type.SetClangType(valobj_sp->GetClangAST(), valobj_sp->GetClangType());
} else {
}
else
{
const char *error_cstr = error.AsCString(NULL);
if (error_cstr)
result.GetErrorStream().Printf("error: %s\n", error_cstr);
@ -1084,10 +1085,12 @@ protected:
uint32_t watch_type = m_option_watchpoint.watch_type;
error.Clear();
Watchpoint *wp = target->CreateWatchpoint(addr, size, &type, watch_type, error).get();
if (wp) {
if (wp)
{
wp->SetWatchSpec(command.GetArgumentAtIndex(0));
wp->SetWatchVariable(true);
if (var_sp && var_sp->GetDeclaration().GetFile()) {
if (var_sp && var_sp->GetDeclaration().GetFile())
{
StreamString ss;
// True to show fullpath for declaration file.
var_sp->GetDeclaration().DumpStopContext(&ss, true);
@ -1097,7 +1100,9 @@ protected:
wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
output_stream.EOL();
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
}
else
{
result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu, variable expression='%s').\n",
addr, size, command.GetArgumentAtIndex(0));
if (error.AsCString(NULL))
@ -1135,7 +1140,10 @@ public:
"If watchpoint setting fails, consider disable/delete existing ones "
"to free up resources.",
NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
eFlagRequiresFrame |
eFlagTryTargetAPILock |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_option_group (interpreter),
m_option_watchpoint ()
{
@ -1182,14 +1190,7 @@ protected:
DoExecute (const char *raw_command, CommandReturnObject &result)
{
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
StackFrame *frame = exe_ctx.GetFramePtr();
if (frame == NULL)
{
result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
result.SetStatus (eReturnStatusFailed);
return false;
}
StackFrame *frame = m_exe_ctx.GetFramePtr();
Args command(raw_command);
@ -1247,7 +1248,8 @@ protected:
frame,
valobj_sp,
options);
if (expr_result != eExecutionCompleted) {
if (expr_result != eExecutionCompleted)
{
result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n");
result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str());
result.SetStatus(eReturnStatusFailed);
@ -1257,7 +1259,8 @@ protected:
// Get the address to watch.
bool success = false;
addr = valobj_sp->GetValueAsUnsigned(0, &success);
if (!success) {
if (!success)
{
result.GetErrorStream().Printf("error: expression did not evaluate to an address\n");
result.SetStatus(eReturnStatusFailed);
return false;
@ -1276,8 +1279,10 @@ protected:
Error error;
Watchpoint *wp = target->CreateWatchpoint(addr, size, &type, watch_type, error).get();
if (wp) {
if (var_sp && var_sp->GetDeclaration().GetFile()) {
if (wp)
{
if (var_sp && var_sp->GetDeclaration().GetFile())
{
StreamString ss;
// True to show fullpath for declaration file.
var_sp->GetDeclaration().DumpStopContext(&ss, true);
@ -1287,7 +1292,9 @@ protected:
wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
output_stream.EOL();
result.SetStatus(eReturnStatusSuccessFinishResult);
} else {
}
else
{
result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu).\n",
addr, size);
if (error.AsCString(NULL))

View File

@ -208,8 +208,77 @@ CommandObject::ParseOptions
bool
CommandObject::CheckFlags (CommandReturnObject &result)
CommandObject::CheckRequirements (CommandReturnObject &result)
{
#ifdef LLDB_CONFIGURATION_DEBUG
// Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx
// has shared pointers to the target, process, thread and frame and we don't
// want any CommandObject instances to keep any of these objects around
// longer than for a single command. Every command should call
// CommandObject::Cleanup() after it has completed
assert (m_exe_ctx.GetTargetPtr() == NULL);
assert (m_exe_ctx.GetProcessPtr() == NULL);
assert (m_exe_ctx.GetThreadPtr() == NULL);
assert (m_exe_ctx.GetFramePtr() == NULL);
#endif
// Lock down the interpreter's execution context prior to running the
// command so we guarantee the selected target, process, thread and frame
// can't go away during the execution
m_exe_ctx = m_interpreter.GetExecutionContext();
const uint32_t flags = GetFlags().Get();
if (flags & (eFlagRequiresTarget |
eFlagRequiresProcess |
eFlagRequiresThread |
eFlagRequiresFrame |
eFlagTryTargetAPILock ))
{
if ((flags & eFlagRequiresTarget) && !m_exe_ctx.HasTargetScope())
{
result.AppendError (GetInvalidTargetDescription());
return false;
}
if ((flags & eFlagRequiresProcess) && !m_exe_ctx.HasProcessScope())
{
result.AppendError (GetInvalidProcessDescription());
return false;
}
if ((flags & eFlagRequiresThread) && !m_exe_ctx.HasThreadScope())
{
result.AppendError (GetInvalidThreadDescription());
return false;
}
if ((flags & eFlagRequiresFrame) && !m_exe_ctx.HasFrameScope())
{
result.AppendError (GetInvalidFrameDescription());
return false;
}
if ((flags & eFlagRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == NULL))
{
result.AppendError (GetInvalidRegContextDescription());
return false;
}
if (flags & eFlagTryTargetAPILock)
{
Target *target = m_exe_ctx.GetTargetPtr();
if (target)
{
if (m_api_locker.TryLock (target->GetAPIMutex(), NULL) == false)
{
result.AppendError ("failed to get API lock");
return false;
}
}
}
}
if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
{
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
@ -263,6 +332,14 @@ CommandObject::CheckFlags (CommandReturnObject &result)
return true;
}
void
CommandObject::Cleanup ()
{
m_exe_ctx.Clear();
m_api_locker.Unlock();
}
class CommandDictCommandPartialMatch
{
public:
@ -888,14 +965,16 @@ CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &resu
cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
}
if (!CheckFlags(result))
return false;
if (!ParseOptions (cmd_args, result))
return false;
if (CheckRequirements(result))
{
if (ParseOptions (cmd_args, result))
{
// Call the command-specific version of 'Execute', passing it the already processed arguments.
handled = DoExecute (cmd_args, result);
}
}
// Call the command-specific version of 'Execute', passing it the already processed arguments.
handled = DoExecute (cmd_args, result);
Cleanup();
}
return handled;
}
@ -916,10 +995,10 @@ CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result)
}
if (!handled)
{
if (!CheckFlags(result))
return false;
else
if (CheckRequirements(result))
handled = DoExecute (args_string, result);
Cleanup();
}
return handled;
}