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/Interpreter/CommandCompletions.h"
#include "lldb/Core/StringList.h" #include "lldb/Core/StringList.h"
#include "lldb/Core/Flags.h" #include "lldb/Core/Flags.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Target/ExecutionContext.h"
namespace lldb_private { namespace lldb_private {
@ -224,15 +226,91 @@ public:
bool bool
IsPairType (ArgumentRepetitionType arg_repeat_type); 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 bool
ParseOptions (Args& args, ParseOptions (Args& args, CommandReturnObject &result);
CommandReturnObject &result);
void void
SetCommandName (const char *name); SetCommandName (const char *name);
@ -374,19 +452,6 @@ public:
return m_flags; 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. /// 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; Execute (const char *args_string, CommandReturnObject &result) = 0;
protected: 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; CommandInterpreter &m_interpreter;
ExecutionContext m_exe_ctx;
Mutex::Locker m_api_locker;
std::string m_cmd_name; std::string m_cmd_name;
std::string m_cmd_help_short; std::string m_cmd_help_short;
std::string m_cmd_help_long; std::string m_cmd_help_long;

View File

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

View File

@ -561,7 +561,7 @@ private:
// Then use the current stack frame's file. // Then use the current stack frame's file.
if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) 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) if (cur_frame == NULL)
{ {
result.AppendError ("No selected frame to use to find the default file."); 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) if (m_options.show_mixed && m_options.num_lines_context == 0)
m_options.num_lines_context = 1; m_options.num_lines_context = 1;
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
// Always show the PC in the disassembly // Always show the PC in the disassembly
uint32_t options = Disassembler::eOptionMarkPCAddress; uint32_t options = Disassembler::eOptionMarkPCAddress;
@ -294,7 +293,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
if (Disassembler::Disassemble (m_interpreter.GetDebugger(), if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.arch, m_options.arch,
plugin_name, plugin_name,
exe_ctx, m_exe_ctx,
name, name,
NULL, // Module * NULL, // Module *
m_options.num_instructions, m_options.num_instructions,
@ -313,7 +312,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
else else
{ {
AddressRange range; AddressRange range;
StackFrame *frame = exe_ctx.GetFramePtr(); StackFrame *frame = m_exe_ctx.GetFramePtr();
if (m_options.frame_line) if (m_options.frame_line)
{ {
if (frame == NULL) if (frame == NULL)
@ -414,7 +413,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
if (Disassembler::Disassemble (m_interpreter.GetDebugger(), if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.arch, m_options.arch,
plugin_name, plugin_name,
exe_ctx, m_exe_ctx,
range.GetBaseAddress(), range.GetBaseAddress(),
m_options.num_instructions, m_options.num_instructions,
m_options.show_mixed ? m_options.num_lines_context : 0, 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(), if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
m_options.arch, m_options.arch,
plugin_name, plugin_name,
exe_ctx, m_exe_ctx,
range, range,
m_options.num_instructions, m_options.num_instructions,
m_options.show_mixed ? m_options.num_lines_context : 0, m_options.show_mixed ? m_options.num_lines_context : 0,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -45,7 +45,10 @@ public:
"register read", "register read",
"Dump the contents of one or more register values from the current frame. If no register is specified, dumps them all.", "Dump the contents of one or more register values from the current frame. If no register is specified, dumps them all.",
NULL, NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), eFlagRequiresFrame |
eFlagRequiresRegContext |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused ),
m_option_group (interpreter), m_option_group (interpreter),
m_format_options (eFormatDefault), m_format_options (eFormatDefault),
m_command_options () m_command_options ()
@ -165,88 +168,79 @@ protected:
DoExecute (Args& command, CommandReturnObject &result) DoExecute (Args& command, CommandReturnObject &result)
{ {
Stream &strm = result.GetOutputStream(); Stream &strm = result.GetOutputStream();
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
if (reg_ctx) const RegisterInfo *reg_info = NULL;
if (command.GetArgumentCount() == 0)
{ {
const RegisterInfo *reg_info = NULL; uint32_t set_idx;
if (command.GetArgumentCount() == 0)
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; for (uint32_t i=0; i<set_array_size; ++i)
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) 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 (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
if (set_idx != UINT32_MAX)
{ {
if (!DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx)) result.AppendErrorWithFormat ("invalid register set index: %u\n", 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.SetStatus (eReturnStatusFailed); result.SetStatus (eReturnStatusFailed);
break; break;
} }
} }
} else
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)
{ {
// When dump_all_sets option is set, dump primitive as well as derived registers. result.AppendError ("invalid register set index\n");
DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue()); result.SetStatus (eReturnStatusFailed);
break;
} }
} }
} }
else else
{ {
if (m_command_options.dump_all_sets) if (m_command_options.dump_all_sets)
{ num_register_sets = reg_ctx->GetRegisterSetCount();
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) for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
{ {
if (!DumpRegister (exe_ctx, strm, reg_ctx, reg_info)) // When dump_all_sets option is set, dump primitive as well as derived registers.
strm.Printf("%-12s = error: unavailable\n", reg_info->name); DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
}
else
{
result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
}
}
} }
} }
} }
else else
{ {
result.AppendError ("no current frame"); if (m_command_options.dump_all_sets)
result.SetStatus (eReturnStatusFailed); {
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(); return result.Succeeded();
} }
@ -366,7 +360,10 @@ public:
"register write", "register write",
"Modify a single register value.", "Modify a single register value.",
NULL, NULL,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) eFlagRequiresFrame |
eFlagRequiresRegContext |
eFlagProcessMustBeLaunched |
eFlagProcessMustBePaused)
{ {
CommandArgumentEntry arg1; CommandArgumentEntry arg1;
CommandArgumentEntry arg2; CommandArgumentEntry arg2;
@ -402,65 +399,56 @@ protected:
DoExecute(Args& command, CommandReturnObject &result) DoExecute(Args& command, CommandReturnObject &result)
{ {
DataExtractor reg_data; DataExtractor reg_data;
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
RegisterContext *reg_ctx = 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); result.SetStatus (eReturnStatusFailed);
} }
else else
{ {
const char *reg_name = command.GetArgumentAtIndex(0); result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
const char *value_str = command.GetArgumentAtIndex(1); result.SetStatus (eReturnStatusFailed);
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);
}
} }
} }
else
{
result.AppendError ("no current frame");
result.SetStatus (eReturnStatusFailed);
}
return result.Succeeded(); return result.Succeeded();
} }
}; };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -208,8 +208,77 @@ CommandObject::ParseOptions
bool 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)) if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
{ {
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
@ -263,6 +332,14 @@ CommandObject::CheckFlags (CommandReturnObject &result)
return true; return true;
} }
void
CommandObject::Cleanup ()
{
m_exe_ctx.Clear();
m_api_locker.Unlock();
}
class CommandDictCommandPartialMatch class CommandDictCommandPartialMatch
{ {
public: public:
@ -888,14 +965,16 @@ CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &resu
cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str)); cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
} }
if (!CheckFlags(result)) if (CheckRequirements(result))
return false; {
if (ParseOptions (cmd_args, result))
if (!ParseOptions (cmd_args, result)) {
return false; // 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. Cleanup();
handled = DoExecute (cmd_args, result);
} }
return handled; return handled;
} }
@ -916,10 +995,10 @@ CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result)
} }
if (!handled) if (!handled)
{ {
if (!CheckFlags(result)) if (CheckRequirements(result))
return false;
else
handled = DoExecute (args_string, result); handled = DoExecute (args_string, result);
Cleanup();
} }
return handled; return handled;
} }