forked from OSchip/llvm-project
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:
parent
eb9ae76864
commit
f9fc609fe7
|
@ -20,6 +20,8 @@
|
|||
#include "lldb/Interpreter/CommandCompletions.h"
|
||||
#include "lldb/Core/StringList.h"
|
||||
#include "lldb/Core/Flags.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
|
@ -224,15 +226,91 @@ public:
|
|||
bool
|
||||
IsPairType (ArgumentRepetitionType arg_repeat_type);
|
||||
|
||||
enum
|
||||
enum
|
||||
{
|
||||
eFlagProcessMustBeLaunched = (1 << 0),
|
||||
eFlagProcessMustBePaused = (1 << 1)
|
||||
//----------------------------------------------------------------------
|
||||
// eFlagRequiresTarget
|
||||
//
|
||||
// Ensures a valid target is contained in m_exe_ctx prior to executing
|
||||
// the command. If a target doesn't exist or is invalid, the command
|
||||
// will fail and CommandObject::GetInvalidTargetDescription() will be
|
||||
// returned as the error. CommandObject subclasses can override the
|
||||
// virtual function for GetInvalidTargetDescription() to provide custom
|
||||
// strings when needed.
|
||||
//----------------------------------------------------------------------
|
||||
eFlagRequiresTarget = (1u << 0),
|
||||
//----------------------------------------------------------------------
|
||||
// eFlagRequiresProcess
|
||||
//
|
||||
// Ensures a valid process is contained in m_exe_ctx prior to executing
|
||||
// the command. If a process doesn't exist or is invalid, the command
|
||||
// will fail and CommandObject::GetInvalidProcessDescription() will be
|
||||
// returned as the error. CommandObject subclasses can override the
|
||||
// virtual function for GetInvalidProcessDescription() to provide custom
|
||||
// strings when needed.
|
||||
//----------------------------------------------------------------------
|
||||
eFlagRequiresProcess = (1u << 1),
|
||||
//----------------------------------------------------------------------
|
||||
// eFlagRequiresThread
|
||||
//
|
||||
// Ensures a valid thread is contained in m_exe_ctx prior to executing
|
||||
// the command. If a thread doesn't exist or is invalid, the command
|
||||
// will fail and CommandObject::GetInvalidThreadDescription() will be
|
||||
// returned as the error. CommandObject subclasses can override the
|
||||
// virtual function for GetInvalidThreadDescription() to provide custom
|
||||
// strings when needed.
|
||||
//----------------------------------------------------------------------
|
||||
eFlagRequiresThread = (1u << 2),
|
||||
//----------------------------------------------------------------------
|
||||
// eFlagRequiresFrame
|
||||
//
|
||||
// Ensures a valid frame is contained in m_exe_ctx prior to executing
|
||||
// the command. If a frame doesn't exist or is invalid, the command
|
||||
// will fail and CommandObject::GetInvalidFrameDescription() will be
|
||||
// returned as the error. CommandObject subclasses can override the
|
||||
// virtual function for GetInvalidFrameDescription() to provide custom
|
||||
// strings when needed.
|
||||
//----------------------------------------------------------------------
|
||||
eFlagRequiresFrame = (1u << 3),
|
||||
//----------------------------------------------------------------------
|
||||
// eFlagRequiresRegContext
|
||||
//
|
||||
// Ensures a valid register context (from the selected frame if there
|
||||
// is a frame in m_exe_ctx, or from the selected thread from m_exe_ctx)
|
||||
// is availble from m_exe_ctx prior to executing the command. If a
|
||||
// target doesn't exist or is invalid, the command will fail and
|
||||
// CommandObject::GetInvalidRegContextDescription() will be returned as
|
||||
// the error. CommandObject subclasses can override the virtual function
|
||||
// for GetInvalidRegContextDescription() to provide custom strings when
|
||||
// needed.
|
||||
//----------------------------------------------------------------------
|
||||
eFlagRequiresRegContext = (1u << 4),
|
||||
//----------------------------------------------------------------------
|
||||
// eFlagTryTargetAPILock
|
||||
//
|
||||
// Attempts to acquire the target lock if a target is selected in the
|
||||
// command interpreter. If the command object fails to acquire the API
|
||||
// lock, the command will fail with an appropriate error message.
|
||||
//----------------------------------------------------------------------
|
||||
eFlagTryTargetAPILock = (1u << 5),
|
||||
//----------------------------------------------------------------------
|
||||
// eFlagProcessMustBeLaunched
|
||||
//
|
||||
// Verifies that there is a launched process in m_exe_ctx, if there
|
||||
// isn't, the command will fail with an appropriate error message.
|
||||
//----------------------------------------------------------------------
|
||||
eFlagProcessMustBeLaunched = (1u << 6),
|
||||
//----------------------------------------------------------------------
|
||||
// eFlagProcessMustBePaused
|
||||
//
|
||||
// Verifies that there is a paused process in m_exe_ctx, if there
|
||||
// isn't, the command will fail with an appropriate error message.
|
||||
//----------------------------------------------------------------------
|
||||
eFlagProcessMustBePaused = (1u << 7)
|
||||
};
|
||||
|
||||
bool
|
||||
ParseOptions (Args& args,
|
||||
CommandReturnObject &result);
|
||||
ParseOptions (Args& args, CommandReturnObject &result);
|
||||
|
||||
void
|
||||
SetCommandName (const char *name);
|
||||
|
@ -374,19 +452,6 @@ public:
|
|||
return m_flags;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Check the command flags against the interpreter's current execution context.
|
||||
///
|
||||
/// @param[out] result
|
||||
/// A command result object, if it is not okay to run the command this will be
|
||||
/// filled in with a suitable error.
|
||||
///
|
||||
/// @return
|
||||
/// \b true if it is okay to run this command, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
CheckFlags (CommandReturnObject &result);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Get the command that appropriate for a "repeat" of the current command.
|
||||
///
|
||||
|
@ -426,7 +491,56 @@ public:
|
|||
Execute (const char *args_string, CommandReturnObject &result) = 0;
|
||||
|
||||
protected:
|
||||
virtual const char *
|
||||
GetInvalidTargetDescription()
|
||||
{
|
||||
return "invalid target, create a target using the 'target create' command";
|
||||
}
|
||||
|
||||
virtual const char *
|
||||
GetInvalidProcessDescription()
|
||||
{
|
||||
return "invalid process";
|
||||
}
|
||||
|
||||
virtual const char *
|
||||
GetInvalidThreadDescription()
|
||||
{
|
||||
return "invalid thread";
|
||||
}
|
||||
|
||||
virtual const char *
|
||||
GetInvalidFrameDescription()
|
||||
{
|
||||
return "invalid frame";
|
||||
}
|
||||
|
||||
virtual const char *
|
||||
GetInvalidRegContextDescription ()
|
||||
{
|
||||
return "invalid frame, no registers";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Check the command to make sure anything required by this
|
||||
/// command is available.
|
||||
///
|
||||
/// @param[out] result
|
||||
/// A command result object, if it is not okay to run the command
|
||||
/// this will be filled in with a suitable error.
|
||||
///
|
||||
/// @return
|
||||
/// \b true if it is okay to run this command, \b false otherwise.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
CheckRequirements (CommandReturnObject &result);
|
||||
|
||||
void
|
||||
Cleanup ();
|
||||
|
||||
CommandInterpreter &m_interpreter;
|
||||
ExecutionContext m_exe_ctx;
|
||||
Mutex::Locker m_api_locker;
|
||||
std::string m_cmd_name;
|
||||
std::string m_cmd_help_short;
|
||||
std::string m_cmd_help_long;
|
||||
|
|
|
@ -104,7 +104,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
|
|||
ConstString target_triple;
|
||||
|
||||
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (!process)
|
||||
{
|
||||
result.AppendError ("Args found no process.");
|
||||
|
@ -130,7 +130,7 @@ CommandObjectArgs::DoExecute (Args& args, CommandReturnObject &result)
|
|||
return false;
|
||||
}
|
||||
|
||||
Thread *thread = m_interpreter.GetExecutionContext ().GetThreadPtr();
|
||||
Thread *thread = m_exe_ctx.GetThreadPtr();
|
||||
|
||||
if (!thread)
|
||||
{
|
||||
|
|
|
@ -561,7 +561,7 @@ private:
|
|||
// Then use the current stack frame's file.
|
||||
if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line))
|
||||
{
|
||||
StackFrame *cur_frame = m_interpreter.GetExecutionContext().GetFramePtr();
|
||||
StackFrame *cur_frame = m_exe_ctx.GetFramePtr();
|
||||
if (cur_frame == NULL)
|
||||
{
|
||||
result.AppendError ("No selected frame to use to find the default file.");
|
||||
|
|
|
@ -273,7 +273,6 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
|
|||
if (m_options.show_mixed && m_options.num_lines_context == 0)
|
||||
m_options.num_lines_context = 1;
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
// Always show the PC in the disassembly
|
||||
uint32_t options = Disassembler::eOptionMarkPCAddress;
|
||||
|
||||
|
@ -294,7 +293,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
|
|||
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
|
||||
m_options.arch,
|
||||
plugin_name,
|
||||
exe_ctx,
|
||||
m_exe_ctx,
|
||||
name,
|
||||
NULL, // Module *
|
||||
m_options.num_instructions,
|
||||
|
@ -313,7 +312,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
|
|||
else
|
||||
{
|
||||
AddressRange range;
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
StackFrame *frame = m_exe_ctx.GetFramePtr();
|
||||
if (m_options.frame_line)
|
||||
{
|
||||
if (frame == NULL)
|
||||
|
@ -414,7 +413,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
|
|||
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
|
||||
m_options.arch,
|
||||
plugin_name,
|
||||
exe_ctx,
|
||||
m_exe_ctx,
|
||||
range.GetBaseAddress(),
|
||||
m_options.num_instructions,
|
||||
m_options.show_mixed ? m_options.num_lines_context : 0,
|
||||
|
@ -460,7 +459,7 @@ CommandObjectDisassemble::DoExecute (Args& command, CommandReturnObject &result)
|
|||
if (Disassembler::Disassemble (m_interpreter.GetDebugger(),
|
||||
m_options.arch,
|
||||
plugin_name,
|
||||
exe_ctx,
|
||||
m_exe_ctx,
|
||||
range,
|
||||
m_options.num_instructions,
|
||||
m_options.show_mixed ? m_options.num_lines_context : 0,
|
||||
|
|
|
@ -168,7 +168,7 @@ CommandObjectExpression::CommandObjectExpression (CommandInterpreter &interprete
|
|||
"expression",
|
||||
"Evaluate a C/ObjC/C++ expression in the current program context, using user defined variables and variables currently in scope.",
|
||||
NULL,
|
||||
eFlagProcessMustBePaused),
|
||||
eFlagProcessMustBePaused | eFlagTryTargetAPILock),
|
||||
m_option_group (interpreter),
|
||||
m_format_options (eFormatDefault),
|
||||
m_command_options (),
|
||||
|
@ -315,7 +315,7 @@ CommandObjectExpression::EvaluateExpression
|
|||
CommandReturnObject *result
|
||||
)
|
||||
{
|
||||
Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
|
||||
if (!target)
|
||||
target = Host::GetDummyTarget(m_interpreter.GetDebugger()).get();
|
||||
|
@ -351,7 +351,7 @@ CommandObjectExpression::EvaluateExpression
|
|||
.SetTimeoutUsec(m_command_options.timeout);
|
||||
|
||||
exe_results = target->EvaluateExpression (expr,
|
||||
m_interpreter.GetExecutionContext().GetFramePtr(),
|
||||
m_exe_ctx.GetFramePtr(),
|
||||
result_valobj_sp,
|
||||
options);
|
||||
|
||||
|
@ -360,7 +360,7 @@ CommandObjectExpression::EvaluateExpression
|
|||
uint32_t start_frame = 0;
|
||||
uint32_t num_frames = 1;
|
||||
uint32_t num_frames_with_source = 0;
|
||||
Thread *thread = m_interpreter.GetExecutionContext().GetThreadPtr();
|
||||
Thread *thread = m_exe_ctx.GetThreadPtr();
|
||||
if (thread)
|
||||
{
|
||||
thread->GetStatus (result->GetOutputStream(),
|
||||
|
@ -370,7 +370,7 @@ CommandObjectExpression::EvaluateExpression
|
|||
}
|
||||
else
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
{
|
||||
bool only_threads_with_stop_reason = true;
|
||||
|
|
|
@ -63,7 +63,10 @@ public:
|
|||
"frame info",
|
||||
"List information about the currently selected frame in the current thread.",
|
||||
"frame info",
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
|
||||
eFlagRequiresFrame |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -73,21 +76,10 @@ public:
|
|||
|
||||
protected:
|
||||
bool
|
||||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
if (frame)
|
||||
{
|
||||
frame->DumpUsingSettingsFormat (&result.GetOutputStream());
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("no current frame");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
m_exe_ctx.GetFrameRef().DumpUsingSettingsFormat (&result.GetOutputStream());
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
return result.Succeeded();
|
||||
}
|
||||
};
|
||||
|
@ -162,7 +154,10 @@ public:
|
|||
"frame select",
|
||||
"Select a frame by index from within the current thread and make it the current frame.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
eFlagRequiresThread |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_options (interpreter)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
|
@ -193,111 +188,104 @@ public:
|
|||
|
||||
protected:
|
||||
bool
|
||||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
|
||||
Thread *thread = exe_ctx.GetThreadPtr();
|
||||
if (thread)
|
||||
// No need to check "thread" for validity as eFlagRequiresThread ensures it is valid
|
||||
Thread *thread = m_exe_ctx.GetThreadPtr();
|
||||
|
||||
uint32_t frame_idx = UINT32_MAX;
|
||||
if (m_options.relative_frame_offset != INT32_MIN)
|
||||
{
|
||||
uint32_t frame_idx = UINT32_MAX;
|
||||
if (m_options.relative_frame_offset != INT32_MIN)
|
||||
// The one and only argument is a signed relative frame index
|
||||
frame_idx = thread->GetSelectedFrameIndex ();
|
||||
if (frame_idx == UINT32_MAX)
|
||||
frame_idx = 0;
|
||||
|
||||
if (m_options.relative_frame_offset < 0)
|
||||
{
|
||||
// The one and only argument is a signed relative frame index
|
||||
frame_idx = thread->GetSelectedFrameIndex ();
|
||||
if (frame_idx == UINT32_MAX)
|
||||
frame_idx = 0;
|
||||
|
||||
if (m_options.relative_frame_offset < 0)
|
||||
{
|
||||
if (frame_idx >= -m_options.relative_frame_offset)
|
||||
frame_idx += m_options.relative_frame_offset;
|
||||
else
|
||||
{
|
||||
if (frame_idx == 0)
|
||||
{
|
||||
//If you are already at the bottom of the stack, then just warn and don't reset the frame.
|
||||
result.AppendError("Already at the bottom of the stack");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
frame_idx = 0;
|
||||
}
|
||||
}
|
||||
else if (m_options.relative_frame_offset > 0)
|
||||
{
|
||||
// I don't want "up 20" where "20" takes you past the top of the stack to produce
|
||||
// an error, but rather to just go to the top. So I have to count the stack here...
|
||||
const uint32_t num_frames = thread->GetStackFrameCount();
|
||||
if (num_frames - frame_idx > m_options.relative_frame_offset)
|
||||
frame_idx += m_options.relative_frame_offset;
|
||||
else
|
||||
{
|
||||
if (frame_idx == num_frames - 1)
|
||||
{
|
||||
//If we are already at the top of the stack, just warn and don't reset the frame.
|
||||
result.AppendError("Already at the top of the stack");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
frame_idx = num_frames - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (command.GetArgumentCount() == 1)
|
||||
{
|
||||
const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
|
||||
frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
|
||||
}
|
||||
else if (command.GetArgumentCount() == 0)
|
||||
{
|
||||
frame_idx = thread->GetSelectedFrameIndex ();
|
||||
if (frame_idx == UINT32_MAX)
|
||||
{
|
||||
frame_idx = 0;
|
||||
}
|
||||
}
|
||||
if (frame_idx >= -m_options.relative_frame_offset)
|
||||
frame_idx += m_options.relative_frame_offset;
|
||||
else
|
||||
{
|
||||
result.AppendError ("invalid arguments.\n");
|
||||
m_options.GenerateOptionUsage (result.GetErrorStream(), this);
|
||||
if (frame_idx == 0)
|
||||
{
|
||||
//If you are already at the bottom of the stack, then just warn and don't reset the frame.
|
||||
result.AppendError("Already at the bottom of the stack");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
frame_idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const bool broadcast = true;
|
||||
bool success = thread->SetSelectedFrameByIndex (frame_idx, broadcast);
|
||||
if (success)
|
||||
else if (m_options.relative_frame_offset > 0)
|
||||
{
|
||||
exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
if (frame)
|
||||
// I don't want "up 20" where "20" takes you past the top of the stack to produce
|
||||
// an error, but rather to just go to the top. So I have to count the stack here...
|
||||
const uint32_t num_frames = thread->GetStackFrameCount();
|
||||
if (num_frames - frame_idx > m_options.relative_frame_offset)
|
||||
frame_idx += m_options.relative_frame_offset;
|
||||
else
|
||||
{
|
||||
bool already_shown = false;
|
||||
SymbolContext frame_sc(frame->GetSymbolContext(eSymbolContextLineEntry));
|
||||
if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
|
||||
if (frame_idx == num_frames - 1)
|
||||
{
|
||||
already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
|
||||
}
|
||||
|
||||
bool show_frame_info = true;
|
||||
bool show_source = !already_shown;
|
||||
if (frame->GetStatus (result.GetOutputStream(), show_frame_info, show_source))
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
return result.Succeeded();
|
||||
//If we are already at the top of the stack, just warn and don't reset the frame.
|
||||
result.AppendError("Already at the top of the stack");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
frame_idx = num_frames - 1;
|
||||
}
|
||||
}
|
||||
result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
result.AppendError ("no current thread");
|
||||
if (command.GetArgumentCount() == 1)
|
||||
{
|
||||
const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
|
||||
frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
|
||||
}
|
||||
else if (command.GetArgumentCount() == 0)
|
||||
{
|
||||
frame_idx = thread->GetSelectedFrameIndex ();
|
||||
if (frame_idx == UINT32_MAX)
|
||||
{
|
||||
frame_idx = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("invalid arguments.\n");
|
||||
m_options.GenerateOptionUsage (result.GetErrorStream(), this);
|
||||
}
|
||||
}
|
||||
|
||||
const bool broadcast = true;
|
||||
bool success = thread->SetSelectedFrameByIndex (frame_idx, broadcast);
|
||||
if (success)
|
||||
{
|
||||
m_exe_ctx.SetFrameSP(thread->GetSelectedFrame ());
|
||||
StackFrame *frame = m_exe_ctx.GetFramePtr();
|
||||
if (frame)
|
||||
{
|
||||
bool already_shown = false;
|
||||
SymbolContext frame_sc(frame->GetSymbolContext(eSymbolContextLineEntry));
|
||||
if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
|
||||
{
|
||||
already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
|
||||
}
|
||||
|
||||
bool show_frame_info = true;
|
||||
bool show_source = !already_shown;
|
||||
if (frame->GetStatus (result.GetOutputStream(), show_frame_info, show_source))
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
return result.Succeeded();
|
||||
}
|
||||
}
|
||||
}
|
||||
result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
@ -331,7 +319,10 @@ public:
|
|||
"Children of aggregate variables can be specified such as "
|
||||
"'var->child.x'.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
eFlagRequiresFrame |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused),
|
||||
m_option_group (interpreter),
|
||||
m_option_variable(true), // Include the frame specific options by passing "true"
|
||||
m_option_format (eFormatDefault),
|
||||
|
@ -372,14 +363,8 @@ protected:
|
|||
virtual bool
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
if (frame == NULL)
|
||||
{
|
||||
result.AppendError ("you must be stopped in a valid stack frame to view frame variables.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
// No need to check "frame" for validity as eFlagRequiresFrame ensures it is valid
|
||||
StackFrame *frame = m_exe_ctx.GetFramePtr();
|
||||
|
||||
Stream &s = result.GetOutputStream();
|
||||
|
||||
|
|
|
@ -298,7 +298,7 @@ public:
|
|||
"memory read",
|
||||
"Read from the memory of the process being debugged.",
|
||||
NULL,
|
||||
eFlagProcessMustBePaused),
|
||||
eFlagRequiresTarget | eFlagProcessMustBePaused),
|
||||
m_option_group (interpreter),
|
||||
m_format_options (eFormatBytesWithASCII, 1, 8),
|
||||
m_memory_options (),
|
||||
|
@ -371,17 +371,11 @@ protected:
|
|||
virtual bool
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
|
||||
Target *target = exe_ctx.GetTargetPtr();
|
||||
if (target == NULL)
|
||||
{
|
||||
result.AppendError("need at least a target to read memory");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
// No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
|
||||
const size_t argc = command.GetArgumentCount();
|
||||
|
||||
|
||||
if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
|
||||
{
|
||||
result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
|
||||
|
@ -496,7 +490,7 @@ protected:
|
|||
}
|
||||
|
||||
ConstString lookup_type_name(type_str.c_str());
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
StackFrame *frame = m_exe_ctx.GetFramePtr();
|
||||
if (frame)
|
||||
{
|
||||
sc = frame->GetSymbolContext (eSymbolContextModule);
|
||||
|
@ -603,7 +597,7 @@ protected:
|
|||
}
|
||||
|
||||
if (argc > 0)
|
||||
addr = Args::StringToAddress(&exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
|
||||
addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
|
||||
|
||||
if (addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
|
@ -615,7 +609,7 @@ protected:
|
|||
|
||||
if (argc == 2)
|
||||
{
|
||||
lldb::addr_t end_addr = Args::StringToAddress(&exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
|
||||
lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
|
||||
if (end_addr == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
result.AppendError("invalid end address expression.");
|
||||
|
@ -742,7 +736,7 @@ protected:
|
|||
}
|
||||
|
||||
|
||||
ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
|
||||
ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
|
||||
if (clang_ast_type.GetOpaqueQualType())
|
||||
{
|
||||
for (uint32_t i = 0; i<item_count; ++i)
|
||||
|
@ -922,7 +916,7 @@ public:
|
|||
"memory write",
|
||||
"Write to the memory of the process being debugged.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched),
|
||||
eFlagRequiresProcess | eFlagProcessMustBeLaunched),
|
||||
m_option_group (interpreter),
|
||||
m_format_options (eFormatBytes, 1, UINT64_MAX),
|
||||
m_memory_options ()
|
||||
|
@ -999,14 +993,8 @@ protected:
|
|||
virtual bool
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Process *process = exe_ctx.GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError("need a process to read memory");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
// No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
|
||||
const size_t argc = command.GetArgumentCount();
|
||||
|
||||
|
@ -1034,7 +1022,7 @@ protected:
|
|||
size_t item_byte_size = byte_size_value.GetCurrentValue();
|
||||
|
||||
Error error;
|
||||
lldb::addr_t addr = Args::StringToAddress (&exe_ctx,
|
||||
lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
|
||||
command.GetArgumentAtIndex(0),
|
||||
LLDB_INVALID_ADDRESS,
|
||||
&error);
|
||||
|
|
|
@ -357,11 +357,11 @@ class CommandObjectPlatformProcessLaunch : public CommandObjectParsed
|
|||
{
|
||||
public:
|
||||
CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
|
||||
CommandObjectParsed (interpreter,
|
||||
CommandObjectParsed (interpreter,
|
||||
"platform process launch",
|
||||
"Launch a new process on a remote platform.",
|
||||
"platform process launch program",
|
||||
0),
|
||||
eFlagRequiresTarget | eFlagTryTargetAPILock),
|
||||
m_options (interpreter)
|
||||
{
|
||||
}
|
||||
|
@ -387,14 +387,7 @@ protected:
|
|||
{
|
||||
Error error;
|
||||
const uint32_t argc = args.GetArgumentCount();
|
||||
Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
|
||||
if (target == NULL)
|
||||
{
|
||||
result.AppendError ("invalid target, create a debug target using the 'target create' command");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
Module *exe_module = target->GetExecutableModulePointer();
|
||||
if (exe_module)
|
||||
{
|
||||
|
|
|
@ -46,7 +46,8 @@ public:
|
|||
CommandObjectParsed (interpreter,
|
||||
"process launch",
|
||||
"Launch the executable in the debugger.",
|
||||
NULL),
|
||||
NULL,
|
||||
eFlagRequiresTarget),
|
||||
m_options (interpreter)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
|
@ -111,13 +112,6 @@ protected:
|
|||
Debugger &debugger = m_interpreter.GetDebugger();
|
||||
Target *target = debugger.GetSelectedTarget().get();
|
||||
Error error;
|
||||
|
||||
if (target == NULL)
|
||||
{
|
||||
result.AppendError ("invalid target, create a debug target using the 'target create' command");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
// If our listener is NULL, users aren't allows to launch
|
||||
char filename[PATH_MAX];
|
||||
const Module *exe_module = target->GetExecutableModulePointer();
|
||||
|
@ -130,7 +124,7 @@ protected:
|
|||
}
|
||||
|
||||
StateType state = eStateInvalid;
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
{
|
||||
state = process->GetState();
|
||||
|
@ -505,7 +499,7 @@ protected:
|
|||
// and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop
|
||||
// ourselves here.
|
||||
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
StateType state = eStateInvalid;
|
||||
if (process)
|
||||
{
|
||||
|
@ -686,7 +680,10 @@ public:
|
|||
"process continue",
|
||||
"Continue execution of all threads in the current process.",
|
||||
"process continue",
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
eFlagRequiresProcess |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_options(interpreter)
|
||||
{
|
||||
}
|
||||
|
@ -754,19 +751,10 @@ protected:
|
|||
};
|
||||
|
||||
bool
|
||||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
bool synchronous_execution = m_interpreter.GetSynchronous ();
|
||||
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("no process to continue");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
StateType state = process->GetState();
|
||||
if (state == eStateStopped)
|
||||
{
|
||||
|
@ -878,6 +866,8 @@ public:
|
|||
"process detach",
|
||||
"Detach from the current process being debugged.",
|
||||
"process detach",
|
||||
eFlagRequiresProcess |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched)
|
||||
{
|
||||
}
|
||||
|
@ -888,17 +878,9 @@ public:
|
|||
|
||||
protected:
|
||||
bool
|
||||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("must have a valid process in order to detach");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
|
||||
Error error (process->Detach());
|
||||
if (error.Success())
|
||||
|
@ -1008,7 +990,7 @@ protected:
|
|||
|
||||
TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
|
||||
Error error;
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
{
|
||||
if (process->IsAlive())
|
||||
|
@ -1112,7 +1094,7 @@ public:
|
|||
virtual CommandObject *
|
||||
GetProxyCommandObject()
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
return process->GetPluginCommandObject();
|
||||
return NULL;
|
||||
|
@ -1134,7 +1116,10 @@ public:
|
|||
"process load",
|
||||
"Load a shared library into the current process.",
|
||||
"process load <filename> [<filename> ...]",
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
|
||||
eFlagRequiresProcess |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1147,13 +1132,7 @@ protected:
|
|||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("must have a valid process in order to load a shared library");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
|
||||
const uint32_t argc = command.GetArgumentCount();
|
||||
|
||||
|
@ -1194,7 +1173,10 @@ public:
|
|||
"process unload",
|
||||
"Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
|
||||
"process unload <index>",
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
|
||||
eFlagRequiresProcess |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1207,13 +1189,7 @@ protected:
|
|||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("must have a valid process in order to load a shared library");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
|
||||
const uint32_t argc = command.GetArgumentCount();
|
||||
|
||||
|
@ -1260,7 +1236,8 @@ public:
|
|||
CommandObjectParsed (interpreter,
|
||||
"process signal",
|
||||
"Send a UNIX signal to the current process being debugged.",
|
||||
NULL)
|
||||
NULL,
|
||||
eFlagRequiresProcess | eFlagTryTargetAPILock)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData signal_arg;
|
||||
|
@ -1285,13 +1262,7 @@ protected:
|
|||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("no process to signal");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
|
||||
if (command.GetArgumentCount() == 1)
|
||||
{
|
||||
|
@ -1348,6 +1319,8 @@ public:
|
|||
"process interrupt",
|
||||
"Interrupt the current process being debugged.",
|
||||
"process interrupt",
|
||||
eFlagRequiresProcess |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched)
|
||||
{
|
||||
}
|
||||
|
@ -1361,7 +1334,7 @@ protected:
|
|||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("no process to halt");
|
||||
|
@ -1411,6 +1384,8 @@ public:
|
|||
"process kill",
|
||||
"Terminate the current process being debugged.",
|
||||
"process kill",
|
||||
eFlagRequiresProcess |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched)
|
||||
{
|
||||
}
|
||||
|
@ -1424,7 +1399,7 @@ protected:
|
|||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("no process to kill");
|
||||
|
@ -1469,7 +1444,7 @@ public:
|
|||
"process status",
|
||||
"Show the current status and location of executing process.",
|
||||
"process status",
|
||||
0)
|
||||
eFlagRequiresProcess | eFlagTryTargetAPILock)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1483,27 +1458,18 @@ public:
|
|||
{
|
||||
Stream &strm = result.GetOutputStream();
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Process *process = exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
{
|
||||
const bool only_threads_with_stop_reason = true;
|
||||
const uint32_t start_frame = 0;
|
||||
const uint32_t num_frames = 1;
|
||||
const uint32_t num_frames_with_source = 1;
|
||||
process->GetStatus(strm);
|
||||
process->GetThreadStatus (strm,
|
||||
only_threads_with_stop_reason,
|
||||
start_frame,
|
||||
num_frames,
|
||||
num_frames_with_source);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("No process.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
// No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
const bool only_threads_with_stop_reason = true;
|
||||
const uint32_t start_frame = 0;
|
||||
const uint32_t num_frames = 1;
|
||||
const uint32_t num_frames_with_source = 1;
|
||||
process->GetStatus(strm);
|
||||
process->GetThreadStatus (strm,
|
||||
only_threads_with_stop_reason,
|
||||
start_frame,
|
||||
num_frames,
|
||||
num_frames_with_source);
|
||||
return result.Succeeded();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -45,7 +45,10 @@ public:
|
|||
"register read",
|
||||
"Dump the contents of one or more register values from the current frame. If no register is specified, dumps them all.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
eFlagRequiresFrame |
|
||||
eFlagRequiresRegContext |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_option_group (interpreter),
|
||||
m_format_options (eFormatDefault),
|
||||
m_command_options ()
|
||||
|
@ -165,88 +168,79 @@ protected:
|
|||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
Stream &strm = result.GetOutputStream();
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
|
||||
RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
|
||||
|
||||
if (reg_ctx)
|
||||
const RegisterInfo *reg_info = NULL;
|
||||
if (command.GetArgumentCount() == 0)
|
||||
{
|
||||
const RegisterInfo *reg_info = NULL;
|
||||
if (command.GetArgumentCount() == 0)
|
||||
uint32_t set_idx;
|
||||
|
||||
uint32_t num_register_sets = 1;
|
||||
const uint32_t set_array_size = m_command_options.set_indexes.GetSize();
|
||||
if (set_array_size > 0)
|
||||
{
|
||||
uint32_t set_idx;
|
||||
|
||||
uint32_t num_register_sets = 1;
|
||||
const uint32_t set_array_size = m_command_options.set_indexes.GetSize();
|
||||
if (set_array_size > 0)
|
||||
for (uint32_t i=0; i<set_array_size; ++i)
|
||||
{
|
||||
for (uint32_t i=0; i<set_array_size; ++i)
|
||||
set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
|
||||
if (set_idx != UINT32_MAX)
|
||||
{
|
||||
set_idx = m_command_options.set_indexes[i]->GetUInt64Value (UINT32_MAX, NULL);
|
||||
if (set_idx != UINT32_MAX)
|
||||
if (!DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx))
|
||||
{
|
||||
if (!DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx))
|
||||
{
|
||||
result.AppendErrorWithFormat ("invalid register set index: %u\n", set_idx);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("invalid register set index\n");
|
||||
result.AppendErrorWithFormat ("invalid register set index: %u\n", set_idx);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_command_options.dump_all_sets)
|
||||
num_register_sets = reg_ctx->GetRegisterSetCount();
|
||||
|
||||
for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
|
||||
else
|
||||
{
|
||||
// When dump_all_sets option is set, dump primitive as well as derived registers.
|
||||
DumpRegisterSet (exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
|
||||
result.AppendError ("invalid register set index\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_command_options.dump_all_sets)
|
||||
{
|
||||
result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
else if (m_command_options.set_indexes.GetSize() > 0)
|
||||
{
|
||||
result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *arg_cstr;
|
||||
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
|
||||
{
|
||||
reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
|
||||
num_register_sets = reg_ctx->GetRegisterSetCount();
|
||||
|
||||
if (reg_info)
|
||||
{
|
||||
if (!DumpRegister (exe_ctx, strm, reg_ctx, reg_info))
|
||||
strm.Printf("%-12s = error: unavailable\n", reg_info->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
|
||||
}
|
||||
}
|
||||
for (set_idx = 0; set_idx < num_register_sets; ++set_idx)
|
||||
{
|
||||
// When dump_all_sets option is set, dump primitive as well as derived registers.
|
||||
DumpRegisterSet (m_exe_ctx, strm, reg_ctx, set_idx, !m_command_options.dump_all_sets.GetCurrentValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("no current frame");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
if (m_command_options.dump_all_sets)
|
||||
{
|
||||
result.AppendError ("the --all option can't be used when registers names are supplied as arguments\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
else if (m_command_options.set_indexes.GetSize() > 0)
|
||||
{
|
||||
result.AppendError ("the --set <set> option can't be used when registers names are supplied as arguments\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *arg_cstr;
|
||||
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
|
||||
{
|
||||
reg_info = reg_ctx->GetRegisterInfoByName(arg_cstr);
|
||||
|
||||
if (reg_info)
|
||||
{
|
||||
if (!DumpRegister (m_exe_ctx, strm, reg_ctx, reg_info))
|
||||
strm.Printf("%-12s = error: unavailable\n", reg_info->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat ("Invalid register name '%s'.\n", arg_cstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
@ -366,7 +360,10 @@ public:
|
|||
"register write",
|
||||
"Modify a single register value.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
|
||||
eFlagRequiresFrame |
|
||||
eFlagRequiresRegContext |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused)
|
||||
{
|
||||
CommandArgumentEntry arg1;
|
||||
CommandArgumentEntry arg2;
|
||||
|
@ -402,65 +399,56 @@ protected:
|
|||
DoExecute(Args& command, CommandReturnObject &result)
|
||||
{
|
||||
DataExtractor reg_data;
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
RegisterContext *reg_ctx = exe_ctx.GetRegisterContext ();
|
||||
RegisterContext *reg_ctx = m_exe_ctx.GetRegisterContext ();
|
||||
|
||||
if (reg_ctx)
|
||||
if (command.GetArgumentCount() != 2)
|
||||
{
|
||||
if (command.GetArgumentCount() != 2)
|
||||
result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *reg_name = command.GetArgumentAtIndex(0);
|
||||
const char *value_str = command.GetArgumentAtIndex(1);
|
||||
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
|
||||
|
||||
if (reg_info)
|
||||
{
|
||||
result.AppendError ("register write takes exactly 2 arguments: <reg-name> <value>");
|
||||
RegisterValue reg_value;
|
||||
|
||||
Error error (reg_value.SetValueFromCString (reg_info, value_str));
|
||||
if (error.Success())
|
||||
{
|
||||
if (reg_ctx->WriteRegister (reg_info, reg_value))
|
||||
{
|
||||
// Toss all frames and anything else in the thread
|
||||
// after a register has been written.
|
||||
m_exe_ctx.GetThreadRef().Flush();
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (error.AsCString())
|
||||
{
|
||||
result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
|
||||
reg_name,
|
||||
value_str,
|
||||
error.AsCString());
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
|
||||
reg_name,
|
||||
value_str);
|
||||
}
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *reg_name = command.GetArgumentAtIndex(0);
|
||||
const char *value_str = command.GetArgumentAtIndex(1);
|
||||
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name);
|
||||
|
||||
if (reg_info)
|
||||
{
|
||||
RegisterValue reg_value;
|
||||
|
||||
Error error (reg_value.SetValueFromCString (reg_info, value_str));
|
||||
if (error.Success())
|
||||
{
|
||||
if (reg_ctx->WriteRegister (reg_info, reg_value))
|
||||
{
|
||||
// Toss all frames and anything else in the thread
|
||||
// after a register has been written.
|
||||
exe_ctx.GetThreadRef().Flush();
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (error.AsCString())
|
||||
{
|
||||
result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s': %s\n",
|
||||
reg_name,
|
||||
value_str,
|
||||
error.AsCString());
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat ("Failed to write register '%s' with value '%s'",
|
||||
reg_name,
|
||||
value_str);
|
||||
}
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
result.AppendErrorWithFormat ("Register not found for '%s'.\n", reg_name);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("no current frame");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -202,12 +202,10 @@ insert-before or insert-after.\n");
|
|||
}
|
||||
else
|
||||
{
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
|
||||
// Complete setting value
|
||||
const char *setting_var_name = input.GetArgumentAtIndex(setting_var_idx);
|
||||
Error error;
|
||||
lldb::OptionValueSP value_sp (m_interpreter.GetDebugger().GetPropertyValue(&exe_ctx, setting_var_name, false, error));
|
||||
lldb::OptionValueSP value_sp (m_interpreter.GetDebugger().GetPropertyValue(&m_exe_ctx, setting_var_name, false, error));
|
||||
if (value_sp)
|
||||
{
|
||||
value_sp->AutoComplete (m_interpreter,
|
||||
|
@ -256,7 +254,6 @@ protected:
|
|||
StripLeadingSpaces(var_value_str);
|
||||
std::string var_value_string = var_value_str.str();
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Error error;
|
||||
if (m_options.m_global)
|
||||
{
|
||||
|
@ -268,7 +265,7 @@ protected:
|
|||
|
||||
if (error.Success())
|
||||
{
|
||||
error = m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
|
||||
error = m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
|
||||
eVarSetOperationAssign,
|
||||
var_name,
|
||||
var_value_string.c_str());
|
||||
|
@ -357,7 +354,6 @@ protected:
|
|||
virtual bool
|
||||
DoExecute (Args& args, CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
|
||||
const size_t argc = args.GetArgumentCount ();
|
||||
|
@ -367,7 +363,7 @@ protected:
|
|||
{
|
||||
const char *property_path = args.GetArgumentAtIndex (i);
|
||||
|
||||
Error error(m_interpreter.GetDebugger().DumpPropertyValue (&exe_ctx, result.GetOutputStream(), property_path, OptionValue::eDumpGroupValue));
|
||||
Error error(m_interpreter.GetDebugger().DumpPropertyValue (&m_exe_ctx, result.GetOutputStream(), property_path, OptionValue::eDumpGroupValue));
|
||||
if (error.Success())
|
||||
{
|
||||
result.GetOutputStream().EOL();
|
||||
|
@ -381,7 +377,7 @@ protected:
|
|||
}
|
||||
else
|
||||
{
|
||||
m_interpreter.GetDebugger().DumpAllPropertyValues (& exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue);
|
||||
m_interpreter.GetDebugger().DumpAllPropertyValues (&m_exe_ctx, result.GetOutputStream(), OptionValue::eDumpGroupValue);
|
||||
}
|
||||
|
||||
return result.Succeeded();
|
||||
|
@ -450,7 +446,6 @@ protected:
|
|||
virtual bool
|
||||
DoExecute (Args& args, CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
|
||||
const bool will_modify = false;
|
||||
|
@ -463,7 +458,7 @@ protected:
|
|||
{
|
||||
const char *property_path = args.GetArgumentAtIndex (i);
|
||||
|
||||
const Property *property = m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath (&exe_ctx, will_modify, property_path);
|
||||
const Property *property = m_interpreter.GetDebugger().GetValueProperties()->GetPropertyAtPath (&m_exe_ctx, will_modify, property_path);
|
||||
|
||||
if (property)
|
||||
{
|
||||
|
@ -592,8 +587,7 @@ protected:
|
|||
StripLeadingSpaces(var_value_str);
|
||||
std::string var_value_string = var_value_str.str();
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Error error (m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
|
||||
Error error (m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
|
||||
eVarSetOperationRemove,
|
||||
var_name,
|
||||
var_value_string.c_str()));
|
||||
|
@ -719,8 +713,7 @@ protected:
|
|||
StripLeadingSpaces(var_value_str);
|
||||
std::string var_value_string = var_value_str.str();
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Error error(m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
|
||||
Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
|
||||
eVarSetOperationReplace,
|
||||
var_name,
|
||||
var_value_string.c_str()));
|
||||
|
@ -853,8 +846,7 @@ protected:
|
|||
StripLeadingSpaces(var_value_str);
|
||||
std::string var_value_string = var_value_str.str();
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Error error(m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
|
||||
Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
|
||||
eVarSetOperationInsertBefore,
|
||||
var_name,
|
||||
var_value_string.c_str()));
|
||||
|
@ -982,8 +974,7 @@ protected:
|
|||
StripLeadingSpaces(var_value_str);
|
||||
std::string var_value_string = var_value_str.str();
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Error error(m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
|
||||
Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
|
||||
eVarSetOperationInsertAfter,
|
||||
var_name,
|
||||
var_value_string.c_str()));
|
||||
|
@ -1102,8 +1093,7 @@ protected:
|
|||
StripLeadingSpaces(var_value_str);
|
||||
std::string var_value_string = var_value_str.str();
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Error error(m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
|
||||
Error error(m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
|
||||
eVarSetOperationAppend,
|
||||
var_name,
|
||||
var_value_string.c_str()));
|
||||
|
@ -1196,8 +1186,7 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Error error (m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
|
||||
Error error (m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
|
||||
eVarSetOperationClear,
|
||||
var_name,
|
||||
NULL));
|
||||
|
|
|
@ -250,7 +250,8 @@ public:
|
|||
CommandObjectParsed (interpreter,
|
||||
"source list",
|
||||
"Display source code (as specified) based on the current executable's debug info.",
|
||||
NULL),
|
||||
NULL,
|
||||
eFlagRequiresTarget),
|
||||
m_options (interpreter)
|
||||
{
|
||||
}
|
||||
|
@ -307,18 +308,7 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Target *target = exe_ctx.GetTargetPtr();
|
||||
|
||||
if (target == NULL)
|
||||
target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
|
||||
if (target == NULL)
|
||||
{
|
||||
result.AppendError ("invalid target, create a debug target using the 'target create' command");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
|
||||
SymbolContextList sc_list;
|
||||
if (!m_options.symbol_name.empty())
|
||||
|
@ -455,7 +445,7 @@ protected:
|
|||
{
|
||||
const bool show_inlines = true;
|
||||
m_breakpoint_locations.Reset (start_file, 0, show_inlines);
|
||||
SearchFilter target_search_filter (exe_ctx.GetTargetSP());
|
||||
SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
|
||||
target_search_filter.Search (m_breakpoint_locations);
|
||||
}
|
||||
else
|
||||
|
@ -556,7 +546,7 @@ protected:
|
|||
bool show_module = true;
|
||||
bool show_inlined_frames = true;
|
||||
sc.DumpStopContext(&result.GetOutputStream(),
|
||||
exe_ctx.GetBestExecutionContextScope(),
|
||||
m_exe_ctx.GetBestExecutionContextScope(),
|
||||
sc.line_entry.range.GetBaseAddress(),
|
||||
show_fullpaths,
|
||||
show_module,
|
||||
|
|
|
@ -600,7 +600,7 @@ public:
|
|||
"target variable",
|
||||
"Read global variable(s) prior to, or while running your binary.",
|
||||
NULL,
|
||||
0),
|
||||
eFlagRequiresTarget),
|
||||
m_option_group (interpreter),
|
||||
m_option_variable (false), // Don't include frame options
|
||||
m_option_format (eFormatDefault),
|
||||
|
@ -769,188 +769,66 @@ protected:
|
|||
virtual bool
|
||||
DoExecute (Args& args, CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
|
||||
Target *target = exe_ctx.GetTargetPtr();
|
||||
if (target)
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
const size_t argc = args.GetArgumentCount();
|
||||
Stream &s = result.GetOutputStream();
|
||||
|
||||
if (argc > 0)
|
||||
{
|
||||
const size_t argc = args.GetArgumentCount();
|
||||
Stream &s = result.GetOutputStream();
|
||||
|
||||
if (argc > 0)
|
||||
|
||||
for (size_t idx = 0; idx < argc; ++idx)
|
||||
{
|
||||
VariableList variable_list;
|
||||
ValueObjectList valobj_list;
|
||||
|
||||
for (size_t idx = 0; idx < argc; ++idx)
|
||||
const char *arg = args.GetArgumentAtIndex(idx);
|
||||
uint32_t matches = 0;
|
||||
bool use_var_name = false;
|
||||
if (m_option_variable.use_regex)
|
||||
{
|
||||
VariableList variable_list;
|
||||
ValueObjectList valobj_list;
|
||||
|
||||
const char *arg = args.GetArgumentAtIndex(idx);
|
||||
uint32_t matches = 0;
|
||||
bool use_var_name = false;
|
||||
if (m_option_variable.use_regex)
|
||||
RegularExpression regex(arg);
|
||||
if (!regex.IsValid ())
|
||||
{
|
||||
RegularExpression regex(arg);
|
||||
if (!regex.IsValid ())
|
||||
{
|
||||
result.GetErrorStream().Printf ("error: invalid regular expression: '%s'\n", arg);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
use_var_name = true;
|
||||
matches = target->GetImages().FindGlobalVariables (regex,
|
||||
true,
|
||||
UINT32_MAX,
|
||||
variable_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
Error error (Variable::GetValuesForVariableExpressionPath (arg,
|
||||
exe_ctx.GetBestExecutionContextScope(),
|
||||
GetVariableCallback,
|
||||
target,
|
||||
variable_list,
|
||||
valobj_list));
|
||||
matches = variable_list.GetSize();
|
||||
}
|
||||
|
||||
if (matches == 0)
|
||||
{
|
||||
result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", arg);
|
||||
result.GetErrorStream().Printf ("error: invalid regular expression: '%s'\n", arg);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t global_idx=0; global_idx<matches; ++global_idx)
|
||||
{
|
||||
VariableSP var_sp (variable_list.GetVariableAtIndex(global_idx));
|
||||
if (var_sp)
|
||||
{
|
||||
ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(global_idx));
|
||||
if (!valobj_sp)
|
||||
valobj_sp = ValueObjectVariable::Create (exe_ctx.GetBestExecutionContextScope(), var_sp);
|
||||
|
||||
if (valobj_sp)
|
||||
DumpValueObject (s, var_sp, valobj_sp, use_var_name ? var_sp->GetName().GetCString() : arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const FileSpecList &compile_units = m_option_compile_units.GetOptionValue().GetCurrentValue();
|
||||
const FileSpecList &shlibs = m_option_shared_libraries.GetOptionValue().GetCurrentValue();
|
||||
SymbolContextList sc_list;
|
||||
const size_t num_compile_units = compile_units.GetSize();
|
||||
const size_t num_shlibs = shlibs.GetSize();
|
||||
if (num_compile_units == 0 && num_shlibs == 0)
|
||||
{
|
||||
bool success = false;
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
CompileUnit *comp_unit = NULL;
|
||||
if (frame)
|
||||
{
|
||||
SymbolContext sc = frame->GetSymbolContext (eSymbolContextCompUnit);
|
||||
if (sc.comp_unit)
|
||||
{
|
||||
const bool can_create = true;
|
||||
VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create));
|
||||
if (comp_unit_varlist_sp)
|
||||
{
|
||||
size_t count = comp_unit_varlist_sp->GetSize();
|
||||
if (count > 0)
|
||||
{
|
||||
DumpGlobalVariableList(exe_ctx, sc, *comp_unit_varlist_sp, s);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
if (frame)
|
||||
{
|
||||
if (comp_unit)
|
||||
result.AppendErrorWithFormat ("no global variables in current compile unit: %s/%s\n",
|
||||
comp_unit->GetDirectory().GetCString(),
|
||||
comp_unit->GetFilename().GetCString());
|
||||
else
|
||||
result.AppendErrorWithFormat ("no debug information for frame %u\n", frame->GetFrameIndex());
|
||||
}
|
||||
else
|
||||
result.AppendError ("'target variable' takes one or more global variable names as arguments\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
use_var_name = true;
|
||||
matches = target->GetImages().FindGlobalVariables (regex,
|
||||
true,
|
||||
UINT32_MAX,
|
||||
variable_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
SymbolContextList sc_list;
|
||||
const bool append = true;
|
||||
// We have one or more compile unit or shlib
|
||||
if (num_shlibs > 0)
|
||||
Error error (Variable::GetValuesForVariableExpressionPath (arg,
|
||||
m_exe_ctx.GetBestExecutionContextScope(),
|
||||
GetVariableCallback,
|
||||
target,
|
||||
variable_list,
|
||||
valobj_list));
|
||||
matches = variable_list.GetSize();
|
||||
}
|
||||
|
||||
if (matches == 0)
|
||||
{
|
||||
result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", arg);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint32_t global_idx=0; global_idx<matches; ++global_idx)
|
||||
{
|
||||
for (size_t shlib_idx=0; shlib_idx<num_shlibs; ++shlib_idx)
|
||||
VariableSP var_sp (variable_list.GetVariableAtIndex(global_idx));
|
||||
if (var_sp)
|
||||
{
|
||||
const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
|
||||
ModuleSpec module_spec (module_file);
|
||||
ValueObjectSP valobj_sp (valobj_list.GetValueObjectAtIndex(global_idx));
|
||||
if (!valobj_sp)
|
||||
valobj_sp = ValueObjectVariable::Create (m_exe_ctx.GetBestExecutionContextScope(), var_sp);
|
||||
|
||||
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
|
||||
if (module_sp)
|
||||
{
|
||||
if (num_compile_units > 0)
|
||||
{
|
||||
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
|
||||
module_sp->FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
SymbolContext sc;
|
||||
sc.module_sp = module_sp;
|
||||
sc_list.Append(sc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Didn't find matching shlib/module in target...
|
||||
result.AppendErrorWithFormat ("target doesn't contain the specified shared library: %s%s%s\n",
|
||||
module_file.GetDirectory().GetCString(),
|
||||
module_file.GetDirectory() ? "/" : "",
|
||||
module_file.GetFilename().GetCString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No shared libraries, we just want to find globals for the compile units files that were specified
|
||||
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
|
||||
target->GetImages().FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
|
||||
}
|
||||
|
||||
const uint32_t num_scs = sc_list.GetSize();
|
||||
if (num_scs > 0)
|
||||
{
|
||||
SymbolContext sc;
|
||||
for (uint32_t sc_idx=0; sc_idx<num_scs; ++sc_idx)
|
||||
{
|
||||
if (sc_list.GetContextAtIndex(sc_idx, sc))
|
||||
{
|
||||
if (sc.comp_unit)
|
||||
{
|
||||
const bool can_create = true;
|
||||
VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create));
|
||||
if (comp_unit_varlist_sp)
|
||||
DumpGlobalVariableList(exe_ctx, sc, *comp_unit_varlist_sp, s);
|
||||
}
|
||||
else if (sc.module_sp)
|
||||
{
|
||||
// Get all global variables for this module
|
||||
lldb_private::RegularExpression all_globals_regex("."); // Any global with at least one character
|
||||
VariableList variable_list;
|
||||
sc.module_sp->FindGlobalVariables(all_globals_regex, append, UINT32_MAX, variable_list);
|
||||
DumpGlobalVariableList(exe_ctx, sc, variable_list, s);
|
||||
}
|
||||
}
|
||||
if (valobj_sp)
|
||||
DumpValueObject (s, var_sp, valobj_sp, use_var_name ? var_sp->GetName().GetCString() : arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -958,11 +836,123 @@ protected:
|
|||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("invalid target, create a debug target using the 'target create' command");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
const FileSpecList &compile_units = m_option_compile_units.GetOptionValue().GetCurrentValue();
|
||||
const FileSpecList &shlibs = m_option_shared_libraries.GetOptionValue().GetCurrentValue();
|
||||
SymbolContextList sc_list;
|
||||
const size_t num_compile_units = compile_units.GetSize();
|
||||
const size_t num_shlibs = shlibs.GetSize();
|
||||
if (num_compile_units == 0 && num_shlibs == 0)
|
||||
{
|
||||
bool success = false;
|
||||
StackFrame *frame = m_exe_ctx.GetFramePtr();
|
||||
CompileUnit *comp_unit = NULL;
|
||||
if (frame)
|
||||
{
|
||||
SymbolContext sc = frame->GetSymbolContext (eSymbolContextCompUnit);
|
||||
if (sc.comp_unit)
|
||||
{
|
||||
const bool can_create = true;
|
||||
VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create));
|
||||
if (comp_unit_varlist_sp)
|
||||
{
|
||||
size_t count = comp_unit_varlist_sp->GetSize();
|
||||
if (count > 0)
|
||||
{
|
||||
DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
if (frame)
|
||||
{
|
||||
if (comp_unit)
|
||||
result.AppendErrorWithFormat ("no global variables in current compile unit: %s/%s\n",
|
||||
comp_unit->GetDirectory().GetCString(),
|
||||
comp_unit->GetFilename().GetCString());
|
||||
else
|
||||
result.AppendErrorWithFormat ("no debug information for frame %u\n", frame->GetFrameIndex());
|
||||
}
|
||||
else
|
||||
result.AppendError ("'target variable' takes one or more global variable names as arguments\n");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SymbolContextList sc_list;
|
||||
const bool append = true;
|
||||
// We have one or more compile unit or shlib
|
||||
if (num_shlibs > 0)
|
||||
{
|
||||
for (size_t shlib_idx=0; shlib_idx<num_shlibs; ++shlib_idx)
|
||||
{
|
||||
const FileSpec module_file(shlibs.GetFileSpecAtIndex(shlib_idx));
|
||||
ModuleSpec module_spec (module_file);
|
||||
|
||||
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
|
||||
if (module_sp)
|
||||
{
|
||||
if (num_compile_units > 0)
|
||||
{
|
||||
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
|
||||
module_sp->FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
SymbolContext sc;
|
||||
sc.module_sp = module_sp;
|
||||
sc_list.Append(sc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Didn't find matching shlib/module in target...
|
||||
result.AppendErrorWithFormat ("target doesn't contain the specified shared library: %s%s%s\n",
|
||||
module_file.GetDirectory().GetCString(),
|
||||
module_file.GetDirectory() ? "/" : "",
|
||||
module_file.GetFilename().GetCString());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No shared libraries, we just want to find globals for the compile units files that were specified
|
||||
for (size_t cu_idx=0; cu_idx<num_compile_units; ++cu_idx)
|
||||
target->GetImages().FindCompileUnits(compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list);
|
||||
}
|
||||
|
||||
const uint32_t num_scs = sc_list.GetSize();
|
||||
if (num_scs > 0)
|
||||
{
|
||||
SymbolContext sc;
|
||||
for (uint32_t sc_idx=0; sc_idx<num_scs; ++sc_idx)
|
||||
{
|
||||
if (sc_list.GetContextAtIndex(sc_idx, sc))
|
||||
{
|
||||
if (sc.comp_unit)
|
||||
{
|
||||
const bool can_create = true;
|
||||
VariableListSP comp_unit_varlist_sp (sc.comp_unit->GetVariableList(can_create));
|
||||
if (comp_unit_varlist_sp)
|
||||
DumpGlobalVariableList(m_exe_ctx, sc, *comp_unit_varlist_sp, s);
|
||||
}
|
||||
else if (sc.module_sp)
|
||||
{
|
||||
// Get all global variables for this module
|
||||
lldb_private::RegularExpression all_globals_regex("."); // Any global with at least one character
|
||||
VariableList variable_list;
|
||||
sc.module_sp->FindGlobalVariables(all_globals_regex, append, UINT32_MAX, variable_list);
|
||||
DumpGlobalVariableList(m_exe_ctx, sc, variable_list, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_interpreter.TruncationWarningNecessary())
|
||||
{
|
||||
result.GetOutputStream().Printf(m_interpreter.TruncationWarningText(),
|
||||
|
@ -1997,10 +1987,11 @@ class CommandObjectTargetModulesSourceFileAutoComplete : public CommandObjectPar
|
|||
public:
|
||||
|
||||
CommandObjectTargetModulesSourceFileAutoComplete (CommandInterpreter &interpreter,
|
||||
const char *name,
|
||||
const char *help,
|
||||
const char *syntax) :
|
||||
CommandObjectParsed (interpreter, name, help, syntax)
|
||||
const char *name,
|
||||
const char *help,
|
||||
const char *syntax,
|
||||
uint32_t flags) :
|
||||
CommandObjectParsed (interpreter, name, help, syntax, flags)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData source_file_arg;
|
||||
|
@ -2461,9 +2452,10 @@ class CommandObjectTargetModulesDumpLineTable : public CommandObjectTargetModule
|
|||
public:
|
||||
CommandObjectTargetModulesDumpLineTable (CommandInterpreter &interpreter) :
|
||||
CommandObjectTargetModulesSourceFileAutoComplete (interpreter,
|
||||
"target modules dump line-table",
|
||||
"Dump the debug symbol file for one or more target modules.",
|
||||
NULL)
|
||||
"target modules dump line-table",
|
||||
"Dump the debug symbol file for one or more target modules.",
|
||||
NULL,
|
||||
eFlagRequiresTarget)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2477,65 +2469,55 @@ protected:
|
|||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
if (target == NULL)
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
uint32_t total_num_dumped = 0;
|
||||
|
||||
uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
|
||||
result.GetOutputStream().SetAddressByteSize(addr_byte_size);
|
||||
result.GetErrorStream().SetAddressByteSize(addr_byte_size);
|
||||
|
||||
if (command.GetArgumentCount() == 0)
|
||||
{
|
||||
result.AppendError ("invalid target, create a debug target using the 'target create' command");
|
||||
result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
uint32_t total_num_dumped = 0;
|
||||
|
||||
uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
|
||||
result.GetOutputStream().SetAddressByteSize(addr_byte_size);
|
||||
result.GetErrorStream().SetAddressByteSize(addr_byte_size);
|
||||
|
||||
if (command.GetArgumentCount() == 0)
|
||||
// Dump specified images (by basename or fullpath)
|
||||
const char *arg_cstr;
|
||||
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
|
||||
{
|
||||
result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Dump specified images (by basename or fullpath)
|
||||
const char *arg_cstr;
|
||||
for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
|
||||
FileSpec file_spec(arg_cstr, false);
|
||||
|
||||
const ModuleList &target_modules = target->GetImages();
|
||||
Mutex::Locker modules_locker(target_modules.GetMutex());
|
||||
const uint32_t num_modules = target_modules.GetSize();
|
||||
if (num_modules > 0)
|
||||
{
|
||||
FileSpec file_spec(arg_cstr, false);
|
||||
|
||||
const ModuleList &target_modules = target->GetImages();
|
||||
Mutex::Locker modules_locker(target_modules.GetMutex());
|
||||
const uint32_t num_modules = target_modules.GetSize();
|
||||
if (num_modules > 0)
|
||||
uint32_t num_dumped = 0;
|
||||
for (uint32_t i = 0; i<num_modules; ++i)
|
||||
{
|
||||
uint32_t num_dumped = 0;
|
||||
for (uint32_t i = 0; i<num_modules; ++i)
|
||||
{
|
||||
if (DumpCompileUnitLineTable (m_interpreter,
|
||||
result.GetOutputStream(),
|
||||
target_modules.GetModulePointerAtIndexUnlocked(i),
|
||||
file_spec,
|
||||
exe_ctx.GetProcessPtr() && exe_ctx.GetProcessRef().IsAlive()))
|
||||
num_dumped++;
|
||||
}
|
||||
if (num_dumped == 0)
|
||||
result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
|
||||
else
|
||||
total_num_dumped += num_dumped;
|
||||
if (DumpCompileUnitLineTable (m_interpreter,
|
||||
result.GetOutputStream(),
|
||||
target_modules.GetModulePointerAtIndexUnlocked(i),
|
||||
file_spec,
|
||||
m_exe_ctx.GetProcessPtr() && m_exe_ctx.GetProcessRef().IsAlive()))
|
||||
num_dumped++;
|
||||
}
|
||||
if (num_dumped == 0)
|
||||
result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
|
||||
else
|
||||
total_num_dumped += num_dumped;
|
||||
}
|
||||
}
|
||||
|
||||
if (total_num_dumped > 0)
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
else
|
||||
{
|
||||
result.AppendError ("no source filenames matched any command arguments");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
}
|
||||
|
||||
if (total_num_dumped > 0)
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
else
|
||||
{
|
||||
result.AppendError ("no source filenames matched any command arguments");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
@ -3475,10 +3457,10 @@ public:
|
|||
public:
|
||||
|
||||
CommandOptions (CommandInterpreter &interpreter) :
|
||||
Options(interpreter),
|
||||
m_type(eLookupTypeInvalid),
|
||||
m_str(),
|
||||
m_addr(LLDB_INVALID_ADDRESS)
|
||||
Options(interpreter),
|
||||
m_type(eLookupTypeInvalid),
|
||||
m_str(),
|
||||
m_addr(LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -3541,7 +3523,11 @@ public:
|
|||
CommandObjectParsed (interpreter,
|
||||
"target modules show-unwind",
|
||||
"Show synthesized unwind instructions for a function.",
|
||||
NULL),
|
||||
NULL,
|
||||
eFlagRequiresTarget |
|
||||
eFlagRequiresProcess |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_options (interpreter)
|
||||
{
|
||||
}
|
||||
|
@ -3563,16 +3549,8 @@ protected:
|
|||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
if (!target)
|
||||
{
|
||||
result.AppendError ("invalid target, create a debug target using the 'target create' command");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
ExecutionContext exe_ctx = m_interpreter.GetDebugger().GetSelectedExecutionContext();
|
||||
Process *process = exe_ctx.GetProcessPtr();
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
ABI *abi = NULL;
|
||||
if (process)
|
||||
abi = process->GetABI().get();
|
||||
|
@ -3837,7 +3815,8 @@ public:
|
|||
CommandObjectParsed (interpreter,
|
||||
"target modules lookup",
|
||||
"Look up information within executable and dependent shared library images.",
|
||||
NULL),
|
||||
NULL,
|
||||
eFlagRequiresTarget),
|
||||
m_options (interpreter)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
|
@ -3881,9 +3860,7 @@ public:
|
|||
break;
|
||||
}
|
||||
|
||||
ExecutionContext exe_ctx = interpreter.GetDebugger().GetSelectedExecutionContext();
|
||||
|
||||
StackFrameSP frame = exe_ctx.GetFrameSP();
|
||||
StackFrameSP frame = m_exe_ctx.GetFrameSP();
|
||||
|
||||
if (!frame)
|
||||
return false;
|
||||
|
@ -4375,198 +4352,190 @@ protected:
|
|||
DoExecute (Args& args,
|
||||
CommandReturnObject &result)
|
||||
{
|
||||
ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
|
||||
Target *target = exe_ctx.GetTargetPtr();
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
if (target == NULL)
|
||||
{
|
||||
result.AppendError ("invalid target, create a debug target using the 'target create' command");
|
||||
}
|
||||
else
|
||||
{
|
||||
bool flush = false;
|
||||
ModuleSpec module_spec;
|
||||
const bool uuid_option_set = m_uuid_option_group.GetOptionValue().OptionWasSet();
|
||||
const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
|
||||
const bool frame_option_set = m_current_frame_option.GetOptionValue().OptionWasSet();
|
||||
bool flush = false;
|
||||
ModuleSpec module_spec;
|
||||
const bool uuid_option_set = m_uuid_option_group.GetOptionValue().OptionWasSet();
|
||||
const bool file_option_set = m_file_option.GetOptionValue().OptionWasSet();
|
||||
const bool frame_option_set = m_current_frame_option.GetOptionValue().OptionWasSet();
|
||||
|
||||
const size_t argc = args.GetArgumentCount();
|
||||
if (argc == 0)
|
||||
const size_t argc = args.GetArgumentCount();
|
||||
if (argc == 0)
|
||||
{
|
||||
if (uuid_option_set || file_option_set || frame_option_set)
|
||||
{
|
||||
if (uuid_option_set || file_option_set || frame_option_set)
|
||||
bool success = false;
|
||||
bool error_set = false;
|
||||
if (frame_option_set)
|
||||
{
|
||||
bool success = false;
|
||||
bool error_set = false;
|
||||
if (frame_option_set)
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
{
|
||||
Process *process = exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
const StateType process_state = process->GetState();
|
||||
if (StateIsStoppedState (process_state, true))
|
||||
{
|
||||
const StateType process_state = process->GetState();
|
||||
if (StateIsStoppedState (process_state, true))
|
||||
StackFrame *frame = m_exe_ctx.GetFramePtr();
|
||||
if (frame)
|
||||
{
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
if (frame)
|
||||
ModuleSP frame_module_sp (frame->GetSymbolContext(eSymbolContextModule).module_sp);
|
||||
if (frame_module_sp)
|
||||
{
|
||||
ModuleSP frame_module_sp (frame->GetSymbolContext(eSymbolContextModule).module_sp);
|
||||
if (frame_module_sp)
|
||||
if (frame_module_sp->GetPlatformFileSpec().Exists())
|
||||
{
|
||||
if (frame_module_sp->GetPlatformFileSpec().Exists())
|
||||
{
|
||||
module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
|
||||
module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
|
||||
}
|
||||
module_spec.GetUUID() = frame_module_sp->GetUUID();
|
||||
success = module_spec.GetUUID().IsValid() || module_spec.GetFileSpec();
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("frame has no module");
|
||||
error_set = true;
|
||||
module_spec.GetArchitecture() = frame_module_sp->GetArchitecture();
|
||||
module_spec.GetFileSpec() = frame_module_sp->GetPlatformFileSpec();
|
||||
}
|
||||
module_spec.GetUUID() = frame_module_sp->GetUUID();
|
||||
success = module_spec.GetUUID().IsValid() || module_spec.GetFileSpec();
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("invalid current frame");
|
||||
result.AppendError ("frame has no module");
|
||||
error_set = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat ("process is not stopped: %s", StateAsCString(process_state));
|
||||
result.AppendError ("invalid current frame");
|
||||
error_set = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("a process must exist in order to use the --frame option");
|
||||
result.AppendErrorWithFormat ("process is not stopped: %s", StateAsCString(process_state));
|
||||
error_set = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uuid_option_set)
|
||||
{
|
||||
module_spec.GetUUID() = m_uuid_option_group.GetOptionValue().GetCurrentValue();
|
||||
success |= module_spec.GetUUID().IsValid();
|
||||
}
|
||||
else if (file_option_set)
|
||||
{
|
||||
module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue();
|
||||
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
|
||||
if (module_sp)
|
||||
{
|
||||
module_spec.GetFileSpec() = module_sp->GetFileSpec();
|
||||
module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
|
||||
module_spec.GetUUID() = module_sp->GetUUID();
|
||||
module_spec.GetArchitecture() = module_sp->GetArchitecture();
|
||||
}
|
||||
else
|
||||
{
|
||||
module_spec.GetArchitecture() = target->GetArchitecture();
|
||||
}
|
||||
success |= module_spec.GetFileSpec().Exists();
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (Symbols::DownloadObjectAndSymbolFile (module_spec))
|
||||
{
|
||||
if (module_spec.GetSymbolFileSpec())
|
||||
success = AddModuleSymbols (target, module_spec, flush, result);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success && !error_set)
|
||||
{
|
||||
StreamString error_strm;
|
||||
if (uuid_option_set)
|
||||
{
|
||||
error_strm.PutCString("unable to find debug symbols for UUID ");
|
||||
module_spec.GetUUID().Dump (&error_strm);
|
||||
}
|
||||
else if (file_option_set)
|
||||
{
|
||||
error_strm.PutCString("unable to find debug symbols for the executable file ");
|
||||
error_strm << module_spec.GetFileSpec();
|
||||
}
|
||||
else if (frame_option_set)
|
||||
{
|
||||
error_strm.PutCString("unable to find debug symbols for the current frame");
|
||||
}
|
||||
result.AppendError (error_strm.GetData());
|
||||
result.AppendError ("a process must exist in order to use the --frame option");
|
||||
error_set = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("one or more symbol file paths must be specified, or options must be specified");
|
||||
if (uuid_option_set)
|
||||
{
|
||||
module_spec.GetUUID() = m_uuid_option_group.GetOptionValue().GetCurrentValue();
|
||||
success |= module_spec.GetUUID().IsValid();
|
||||
}
|
||||
else if (file_option_set)
|
||||
{
|
||||
module_spec.GetFileSpec() = m_file_option.GetOptionValue().GetCurrentValue();
|
||||
ModuleSP module_sp (target->GetImages().FindFirstModule(module_spec));
|
||||
if (module_sp)
|
||||
{
|
||||
module_spec.GetFileSpec() = module_sp->GetFileSpec();
|
||||
module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec();
|
||||
module_spec.GetUUID() = module_sp->GetUUID();
|
||||
module_spec.GetArchitecture() = module_sp->GetArchitecture();
|
||||
}
|
||||
else
|
||||
{
|
||||
module_spec.GetArchitecture() = target->GetArchitecture();
|
||||
}
|
||||
success |= module_spec.GetFileSpec().Exists();
|
||||
}
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
if (Symbols::DownloadObjectAndSymbolFile (module_spec))
|
||||
{
|
||||
if (module_spec.GetSymbolFileSpec())
|
||||
success = AddModuleSymbols (target, module_spec, flush, result);
|
||||
}
|
||||
}
|
||||
|
||||
if (!success && !error_set)
|
||||
{
|
||||
StreamString error_strm;
|
||||
if (uuid_option_set)
|
||||
{
|
||||
error_strm.PutCString("unable to find debug symbols for UUID ");
|
||||
module_spec.GetUUID().Dump (&error_strm);
|
||||
}
|
||||
else if (file_option_set)
|
||||
{
|
||||
error_strm.PutCString("unable to find debug symbols for the executable file ");
|
||||
error_strm << module_spec.GetFileSpec();
|
||||
}
|
||||
else if (frame_option_set)
|
||||
{
|
||||
error_strm.PutCString("unable to find debug symbols for the current frame");
|
||||
}
|
||||
result.AppendError (error_strm.GetData());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uuid_option_set)
|
||||
{
|
||||
result.AppendError ("specify either one or more paths to symbol files or use the --uuid option without arguments");
|
||||
}
|
||||
else if (file_option_set)
|
||||
{
|
||||
result.AppendError ("specify either one or more paths to symbol files or use the --file option without arguments");
|
||||
}
|
||||
else if (frame_option_set)
|
||||
{
|
||||
result.AppendError ("specify either one or more paths to symbol files or use the --frame option without arguments");
|
||||
}
|
||||
else
|
||||
{
|
||||
PlatformSP platform_sp (target->GetPlatform());
|
||||
result.AppendError ("one or more symbol file paths must be specified, or options must be specified");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uuid_option_set)
|
||||
{
|
||||
result.AppendError ("specify either one or more paths to symbol files or use the --uuid option without arguments");
|
||||
}
|
||||
else if (file_option_set)
|
||||
{
|
||||
result.AppendError ("specify either one or more paths to symbol files or use the --file option without arguments");
|
||||
}
|
||||
else if (frame_option_set)
|
||||
{
|
||||
result.AppendError ("specify either one or more paths to symbol files or use the --frame option without arguments");
|
||||
}
|
||||
else
|
||||
{
|
||||
PlatformSP platform_sp (target->GetPlatform());
|
||||
|
||||
for (size_t i=0; i<argc; ++i)
|
||||
for (size_t i=0; i<argc; ++i)
|
||||
{
|
||||
const char *symfile_path = args.GetArgumentAtIndex(i);
|
||||
if (symfile_path)
|
||||
{
|
||||
const char *symfile_path = args.GetArgumentAtIndex(i);
|
||||
if (symfile_path)
|
||||
module_spec.GetSymbolFileSpec().SetFile(symfile_path, true);
|
||||
if (platform_sp)
|
||||
{
|
||||
module_spec.GetSymbolFileSpec().SetFile(symfile_path, true);
|
||||
if (platform_sp)
|
||||
{
|
||||
FileSpec symfile_spec;
|
||||
if (platform_sp->ResolveSymbolFile(*target, module_spec, symfile_spec).Success())
|
||||
module_spec.GetSymbolFileSpec() = symfile_spec;
|
||||
}
|
||||
|
||||
ArchSpec arch;
|
||||
bool symfile_exists = module_spec.GetSymbolFileSpec().Exists();
|
||||
FileSpec symfile_spec;
|
||||
if (platform_sp->ResolveSymbolFile(*target, module_spec, symfile_spec).Success())
|
||||
module_spec.GetSymbolFileSpec() = symfile_spec;
|
||||
}
|
||||
|
||||
ArchSpec arch;
|
||||
bool symfile_exists = module_spec.GetSymbolFileSpec().Exists();
|
||||
|
||||
if (symfile_exists)
|
||||
{
|
||||
if (!AddModuleSymbols (target, module_spec, flush, result))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
char resolved_symfile_path[PATH_MAX];
|
||||
if (module_spec.GetSymbolFileSpec().GetPath (resolved_symfile_path, sizeof(resolved_symfile_path)))
|
||||
{
|
||||
if (strcmp (resolved_symfile_path, symfile_path) != 0)
|
||||
{
|
||||
result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", symfile_path, resolved_symfile_path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.AppendErrorWithFormat ("invalid module path '%s'\n", symfile_path);
|
||||
if (symfile_exists)
|
||||
{
|
||||
if (!AddModuleSymbols (target, module_spec, flush, result))
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
char resolved_symfile_path[PATH_MAX];
|
||||
if (module_spec.GetSymbolFileSpec().GetPath (resolved_symfile_path, sizeof(resolved_symfile_path)))
|
||||
{
|
||||
if (strcmp (resolved_symfile_path, symfile_path) != 0)
|
||||
{
|
||||
result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", symfile_path, resolved_symfile_path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
result.AppendErrorWithFormat ("invalid module path '%s'\n", symfile_path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (flush)
|
||||
{
|
||||
Process *process = exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
process->Flush();
|
||||
}
|
||||
if (flush)
|
||||
{
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
process->Flush();
|
||||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
|
|
@ -125,10 +125,14 @@ public:
|
|||
|
||||
CommandObjectThreadBacktrace (CommandInterpreter &interpreter) :
|
||||
CommandObjectParsed (interpreter,
|
||||
"thread backtrace",
|
||||
"Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
"thread backtrace",
|
||||
"Show the stack for one or more threads. If no threads are specified, show the currently selected thread. Use the thread-index \"all\" to see all threads.",
|
||||
NULL,
|
||||
eFlagRequiresProcess |
|
||||
eFlagRequiresThread |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_options(interpreter)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
|
@ -166,28 +170,19 @@ protected:
|
|||
const uint32_t num_frames_with_source = 0;
|
||||
if (command.GetArgumentCount() == 0)
|
||||
{
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Thread *thread = exe_ctx.GetThreadPtr();
|
||||
if (thread)
|
||||
Thread *thread = m_exe_ctx.GetThreadPtr();
|
||||
// Thread::GetStatus() returns the number of frames shown.
|
||||
if (thread->GetStatus (strm,
|
||||
m_options.m_start,
|
||||
m_options.m_count,
|
||||
num_frames_with_source))
|
||||
{
|
||||
// Thread::GetStatus() returns the number of frames shown.
|
||||
if (thread->GetStatus (strm,
|
||||
m_options.m_start,
|
||||
m_options.m_count,
|
||||
num_frames_with_source))
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("invalid thread");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
result.SetStatus (eReturnStatusSuccessFinishResult);
|
||||
}
|
||||
}
|
||||
else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
Mutex::Locker locker (process->GetThreadList().GetMutex());
|
||||
uint32_t num_threads = process->GetThreadList().GetSize();
|
||||
for (uint32_t i = 0; i < num_threads; i++)
|
||||
|
@ -211,7 +206,7 @@ protected:
|
|||
else
|
||||
{
|
||||
uint32_t num_args = command.GetArgumentCount();
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
Mutex::Locker locker (process->GetThreadList().GetMutex());
|
||||
std::vector<ThreadSP> thread_sps;
|
||||
|
||||
|
@ -370,10 +365,14 @@ public:
|
|||
const char *name,
|
||||
const char *help,
|
||||
const char *syntax,
|
||||
uint32_t flags,
|
||||
StepType step_type,
|
||||
StepScope step_scope) :
|
||||
CommandObjectParsed (interpreter, name, help, syntax, flags),
|
||||
CommandObjectParsed (interpreter, name, help, syntax,
|
||||
eFlagRequiresProcess |
|
||||
eFlagRequiresThread |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_step_type (step_type),
|
||||
m_step_scope (step_scope),
|
||||
m_options (interpreter)
|
||||
|
@ -408,169 +407,160 @@ protected:
|
|||
virtual bool
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
bool synchronous_execution = m_interpreter.GetSynchronous();
|
||||
|
||||
if (process == NULL)
|
||||
const uint32_t num_threads = process->GetThreadList().GetSize();
|
||||
Thread *thread = NULL;
|
||||
|
||||
if (command.GetArgumentCount() == 0)
|
||||
{
|
||||
result.AppendError ("need a valid process to step");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t num_threads = process->GetThreadList().GetSize();
|
||||
Thread *thread = NULL;
|
||||
|
||||
if (command.GetArgumentCount() == 0)
|
||||
thread = process->GetThreadList().GetSelectedThread().get();
|
||||
if (thread == NULL)
|
||||
{
|
||||
thread = process->GetThreadList().GetSelectedThread().get();
|
||||
if (thread == NULL)
|
||||
{
|
||||
result.AppendError ("no selected thread in process");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
|
||||
uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
|
||||
if (step_thread_idx == LLDB_INVALID_INDEX32)
|
||||
{
|
||||
result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
|
||||
if (thread == NULL)
|
||||
{
|
||||
result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
|
||||
step_thread_idx, num_threads);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool abort_other_plans = false;
|
||||
const lldb::RunMode stop_other_threads = m_options.m_run_mode;
|
||||
|
||||
// This is a bit unfortunate, but not all the commands in this command object support
|
||||
// only while stepping, so I use the bool for them.
|
||||
bool bool_stop_other_threads;
|
||||
if (m_options.m_run_mode == eAllThreads)
|
||||
bool_stop_other_threads = false;
|
||||
else if (m_options.m_run_mode == eOnlyDuringStepping)
|
||||
{
|
||||
if (m_step_type == eStepTypeOut)
|
||||
bool_stop_other_threads = false;
|
||||
else
|
||||
bool_stop_other_threads = true;
|
||||
}
|
||||
else
|
||||
bool_stop_other_threads = true;
|
||||
|
||||
ThreadPlan *new_plan = NULL;
|
||||
|
||||
if (m_step_type == eStepTypeInto)
|
||||
{
|
||||
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
|
||||
|
||||
if (frame->HasDebugInformation ())
|
||||
{
|
||||
new_plan = thread->QueueThreadPlanForStepInRange (abort_other_plans,
|
||||
frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
|
||||
frame->GetSymbolContext(eSymbolContextEverything),
|
||||
m_options.m_step_in_target.c_str(),
|
||||
stop_other_threads,
|
||||
m_options.m_avoid_no_debug);
|
||||
if (new_plan && !m_options.m_avoid_regexp.empty())
|
||||
{
|
||||
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
|
||||
step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
|
||||
|
||||
}
|
||||
else if (m_step_type == eStepTypeOver)
|
||||
{
|
||||
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
|
||||
|
||||
if (frame->HasDebugInformation())
|
||||
new_plan = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
|
||||
frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
|
||||
frame->GetSymbolContext(eSymbolContextEverything),
|
||||
stop_other_threads);
|
||||
else
|
||||
new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
|
||||
abort_other_plans,
|
||||
bool_stop_other_threads);
|
||||
|
||||
}
|
||||
else if (m_step_type == eStepTypeTrace)
|
||||
{
|
||||
new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
|
||||
}
|
||||
else if (m_step_type == eStepTypeTraceOver)
|
||||
{
|
||||
new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
|
||||
}
|
||||
else if (m_step_type == eStepTypeOut)
|
||||
{
|
||||
new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
|
||||
NULL,
|
||||
false,
|
||||
bool_stop_other_threads,
|
||||
eVoteYes,
|
||||
eVoteNoOpinion,
|
||||
thread->GetSelectedFrameIndex());
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("step type is not supported");
|
||||
result.AppendError ("no selected thread in process");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we got a new plan, then set it to be a master plan (User level Plans should be master plans
|
||||
// so that they can be interruptible). Then resume the process.
|
||||
|
||||
if (new_plan != NULL)
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *thread_idx_cstr = command.GetArgumentAtIndex(0);
|
||||
uint32_t step_thread_idx = Args::StringToUInt32 (thread_idx_cstr, LLDB_INVALID_INDEX32);
|
||||
if (step_thread_idx == LLDB_INVALID_INDEX32)
|
||||
{
|
||||
new_plan->SetIsMasterPlan (true);
|
||||
new_plan->SetOkayToDiscard (false);
|
||||
result.AppendErrorWithFormat ("invalid thread index '%s'.\n", thread_idx_cstr);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
thread = process->GetThreadList().FindThreadByIndexID(step_thread_idx).get();
|
||||
if (thread == NULL)
|
||||
{
|
||||
result.AppendErrorWithFormat ("Thread index %u is out of range (valid values are 0 - %u).\n",
|
||||
step_thread_idx, num_threads);
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
|
||||
process->Resume ();
|
||||
|
||||
const bool abort_other_plans = false;
|
||||
const lldb::RunMode stop_other_threads = m_options.m_run_mode;
|
||||
|
||||
// This is a bit unfortunate, but not all the commands in this command object support
|
||||
// only while stepping, so I use the bool for them.
|
||||
bool bool_stop_other_threads;
|
||||
if (m_options.m_run_mode == eAllThreads)
|
||||
bool_stop_other_threads = false;
|
||||
else if (m_options.m_run_mode == eOnlyDuringStepping)
|
||||
{
|
||||
if (m_step_type == eStepTypeOut)
|
||||
bool_stop_other_threads = false;
|
||||
else
|
||||
bool_stop_other_threads = true;
|
||||
}
|
||||
else
|
||||
bool_stop_other_threads = true;
|
||||
|
||||
if (synchronous_execution)
|
||||
ThreadPlan *new_plan = NULL;
|
||||
|
||||
if (m_step_type == eStepTypeInto)
|
||||
{
|
||||
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
|
||||
|
||||
if (frame->HasDebugInformation ())
|
||||
{
|
||||
new_plan = thread->QueueThreadPlanForStepInRange (abort_other_plans,
|
||||
frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
|
||||
frame->GetSymbolContext(eSymbolContextEverything),
|
||||
m_options.m_step_in_target.c_str(),
|
||||
stop_other_threads,
|
||||
m_options.m_avoid_no_debug);
|
||||
if (new_plan && !m_options.m_avoid_regexp.empty())
|
||||
{
|
||||
StateType state = process->WaitForProcessToStop (NULL);
|
||||
|
||||
//EventSP event_sp;
|
||||
//StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
|
||||
//while (! StateIsStoppedState (state))
|
||||
// {
|
||||
// state = process->WaitForStateChangedEvents (NULL, event_sp);
|
||||
// }
|
||||
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
|
||||
result.SetDidChangeProcessState (true);
|
||||
result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
|
||||
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (new_plan);
|
||||
step_in_range_plan->SetAvoidRegexp(m_options.m_avoid_regexp.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
|
||||
|
||||
}
|
||||
else if (m_step_type == eStepTypeOver)
|
||||
{
|
||||
StackFrame *frame = thread->GetStackFrameAtIndex(0).get();
|
||||
|
||||
if (frame->HasDebugInformation())
|
||||
new_plan = thread->QueueThreadPlanForStepOverRange (abort_other_plans,
|
||||
frame->GetSymbolContext(eSymbolContextEverything).line_entry.range,
|
||||
frame->GetSymbolContext(eSymbolContextEverything),
|
||||
stop_other_threads);
|
||||
else
|
||||
new_plan = thread->QueueThreadPlanForStepSingleInstruction (true,
|
||||
abort_other_plans,
|
||||
bool_stop_other_threads);
|
||||
|
||||
}
|
||||
else if (m_step_type == eStepTypeTrace)
|
||||
{
|
||||
new_plan = thread->QueueThreadPlanForStepSingleInstruction (false, abort_other_plans, bool_stop_other_threads);
|
||||
}
|
||||
else if (m_step_type == eStepTypeTraceOver)
|
||||
{
|
||||
new_plan = thread->QueueThreadPlanForStepSingleInstruction (true, abort_other_plans, bool_stop_other_threads);
|
||||
}
|
||||
else if (m_step_type == eStepTypeOut)
|
||||
{
|
||||
new_plan = thread->QueueThreadPlanForStepOut (abort_other_plans,
|
||||
NULL,
|
||||
false,
|
||||
bool_stop_other_threads,
|
||||
eVoteYes,
|
||||
eVoteNoOpinion,
|
||||
thread->GetSelectedFrameIndex());
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("step type is not supported");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we got a new plan, then set it to be a master plan (User level Plans should be master plans
|
||||
// so that they can be interruptible). Then resume the process.
|
||||
|
||||
if (new_plan != NULL)
|
||||
{
|
||||
new_plan->SetIsMasterPlan (true);
|
||||
new_plan->SetOkayToDiscard (false);
|
||||
|
||||
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
|
||||
process->Resume ();
|
||||
|
||||
|
||||
if (synchronous_execution)
|
||||
{
|
||||
result.AppendError ("Couldn't find thread plan to implement step type.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
StateType state = process->WaitForProcessToStop (NULL);
|
||||
|
||||
//EventSP event_sp;
|
||||
//StateType state = process->WaitForStateChangedEvents (NULL, event_sp);
|
||||
//while (! StateIsStoppedState (state))
|
||||
// {
|
||||
// state = process->WaitForStateChangedEvents (NULL, event_sp);
|
||||
// }
|
||||
process->GetThreadList().SetSelectedThreadByID (thread->GetID());
|
||||
result.SetDidChangeProcessState (true);
|
||||
result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessContinuingNoResult);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("Couldn't find thread plan to implement step type.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
return result.Succeeded();
|
||||
}
|
||||
|
@ -622,7 +612,10 @@ public:
|
|||
"thread continue",
|
||||
"Continue execution of one or more threads in an active process.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
|
||||
eFlagRequiresThread |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData thread_idx_arg;
|
||||
|
@ -656,7 +649,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("no process exists. Cannot continue");
|
||||
|
@ -902,7 +895,10 @@ public:
|
|||
"thread until",
|
||||
"Run the current or specified thread until it reaches a given line number or leaves the current function.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
eFlagRequiresThread |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_options (interpreter)
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
|
@ -946,7 +942,7 @@ protected:
|
|||
return false;
|
||||
}
|
||||
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("need a valid process to step");
|
||||
|
@ -1144,7 +1140,10 @@ public:
|
|||
"thread select",
|
||||
"Select a thread as the currently active thread.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
|
||||
eFlagRequiresProcess |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused )
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData thread_idx_arg;
|
||||
|
@ -1170,7 +1169,7 @@ protected:
|
|||
virtual bool
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
if (process == NULL)
|
||||
{
|
||||
result.AppendError ("no process");
|
||||
|
@ -1217,7 +1216,10 @@ public:
|
|||
"thread list",
|
||||
"Show a summary of all current threads in a process.",
|
||||
"thread list",
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
|
||||
eFlagRequiresProcess |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused )
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -1231,26 +1233,17 @@ protected:
|
|||
{
|
||||
Stream &strm = result.GetOutputStream();
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
Process *process = exe_ctx.GetProcessPtr();
|
||||
if (process)
|
||||
{
|
||||
const bool only_threads_with_stop_reason = false;
|
||||
const uint32_t start_frame = 0;
|
||||
const uint32_t num_frames = 0;
|
||||
const uint32_t num_frames_with_source = 0;
|
||||
process->GetStatus(strm);
|
||||
process->GetThreadStatus (strm,
|
||||
only_threads_with_stop_reason,
|
||||
start_frame,
|
||||
num_frames,
|
||||
num_frames_with_source);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendError ("no current location or status available");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
}
|
||||
Process *process = m_exe_ctx.GetProcessPtr();
|
||||
const bool only_threads_with_stop_reason = false;
|
||||
const uint32_t start_frame = 0;
|
||||
const uint32_t num_frames = 0;
|
||||
const uint32_t num_frames_with_source = 0;
|
||||
process->GetStatus(strm);
|
||||
process->GetThreadStatus (strm,
|
||||
only_threads_with_stop_reason,
|
||||
start_frame,
|
||||
num_frames,
|
||||
num_frames_with_source);
|
||||
return result.Succeeded();
|
||||
}
|
||||
};
|
||||
|
@ -1263,7 +1256,10 @@ public:
|
|||
"thread return",
|
||||
"Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value.",
|
||||
"thread return",
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
|
||||
eFlagRequiresFrame |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused )
|
||||
{
|
||||
CommandArgumentEntry arg;
|
||||
CommandArgumentData expression_arg;
|
||||
|
@ -1293,18 +1289,9 @@ protected:
|
|||
CommandReturnObject &result
|
||||
)
|
||||
{
|
||||
// If there is a command string, pass it to the expression parser:
|
||||
ExecutionContext exe_ctx = m_interpreter.GetExecutionContext();
|
||||
if (!(exe_ctx.HasProcessScope() && exe_ctx.HasThreadScope() && exe_ctx.HasFrameScope()))
|
||||
{
|
||||
result.AppendError("Must have selected process, thread and frame for thread return.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
|
||||
ValueObjectSP return_valobj_sp;
|
||||
|
||||
StackFrameSP frame_sp = exe_ctx.GetFrameSP();
|
||||
StackFrameSP frame_sp = m_exe_ctx.GetFrameSP();
|
||||
uint32_t frame_idx = frame_sp->GetFrameIndex();
|
||||
|
||||
if (frame_sp->IsInlined())
|
||||
|
@ -1316,7 +1303,7 @@ protected:
|
|||
|
||||
if (command && command[0] != '\0')
|
||||
{
|
||||
Target *target = exe_ctx.GetTargetPtr();
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
EvaluateExpressionOptions options;
|
||||
|
||||
options.SetUnwindOnError(true);
|
||||
|
@ -1340,7 +1327,7 @@ protected:
|
|||
}
|
||||
|
||||
Error error;
|
||||
ThreadSP thread_sp = exe_ctx.GetThreadSP();
|
||||
ThreadSP thread_sp = m_exe_ctx.GetThreadSP();
|
||||
const bool broadcast = true;
|
||||
error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp, broadcast);
|
||||
if (!error.Success())
|
||||
|
@ -1377,7 +1364,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
|
|||
"thread step-in",
|
||||
"Source level single step in specified thread (current thread, if none specified).",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
|
||||
eStepTypeInto,
|
||||
eStepScopeSource)));
|
||||
|
||||
|
@ -1386,7 +1372,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
|
|||
"thread step-out",
|
||||
"Finish executing the function of the currently selected frame and return to its call site in specified thread (current thread, if none specified).",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
|
||||
eStepTypeOut,
|
||||
eStepScopeSource)));
|
||||
|
||||
|
@ -1395,7 +1380,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
|
|||
"thread step-over",
|
||||
"Source level single step in specified thread (current thread, if none specified), stepping over calls.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
|
||||
eStepTypeOver,
|
||||
eStepScopeSource)));
|
||||
|
||||
|
@ -1404,7 +1388,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
|
|||
"thread step-inst",
|
||||
"Single step one instruction in specified thread (current thread, if none specified).",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
|
||||
eStepTypeTrace,
|
||||
eStepScopeInstruction)));
|
||||
|
||||
|
@ -1413,7 +1396,6 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
|
|||
"thread step-inst-over",
|
||||
"Single step one instruction in specified thread (current thread, if none specified), stepping over calls.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
|
||||
eStepTypeTraceOver,
|
||||
eStepScopeInstruction)));
|
||||
}
|
||||
|
|
|
@ -934,7 +934,10 @@ public:
|
|||
"If watchpoint setting fails, consider disable/delete existing ones "
|
||||
"to free up resources.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
eFlagRequiresFrame |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_option_group (interpreter),
|
||||
m_option_watchpoint ()
|
||||
{
|
||||
|
@ -988,18 +991,10 @@ protected:
|
|||
}
|
||||
|
||||
virtual bool
|
||||
DoExecute (Args& command,
|
||||
CommandReturnObject &result)
|
||||
DoExecute (Args& command, CommandReturnObject &result)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
if (frame == NULL)
|
||||
{
|
||||
result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
StackFrame *frame = m_exe_ctx.GetFramePtr();
|
||||
|
||||
// If no argument is present, issue an error message. There's no way to set a watchpoint.
|
||||
if (command.GetArgumentCount() <= 0)
|
||||
|
@ -1025,7 +1020,8 @@ protected:
|
|||
Stream &output_stream = result.GetOutputStream();
|
||||
|
||||
// A simple watch variable gesture allows only one argument.
|
||||
if (command.GetArgumentCount() != 1) {
|
||||
if (command.GetArgumentCount() != 1)
|
||||
{
|
||||
result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
|
@ -1041,14 +1037,15 @@ protected:
|
|||
var_sp,
|
||||
error);
|
||||
|
||||
if (!valobj_sp) {
|
||||
if (!valobj_sp)
|
||||
{
|
||||
// Not in the frame; let's check the globals.
|
||||
|
||||
VariableList variable_list;
|
||||
ValueObjectList valobj_list;
|
||||
|
||||
Error error (Variable::GetValuesForVariableExpressionPath (command.GetArgumentAtIndex(0),
|
||||
exe_ctx.GetBestExecutionContextScope(),
|
||||
m_exe_ctx.GetBestExecutionContextScope(),
|
||||
GetVariableCallback,
|
||||
target,
|
||||
variable_list,
|
||||
|
@ -1060,17 +1057,21 @@ protected:
|
|||
|
||||
ClangASTType type;
|
||||
|
||||
if (valobj_sp) {
|
||||
if (valobj_sp)
|
||||
{
|
||||
AddressType addr_type;
|
||||
addr = valobj_sp->GetAddressOf(false, &addr_type);
|
||||
if (addr_type == eAddressTypeLoad) {
|
||||
if (addr_type == eAddressTypeLoad)
|
||||
{
|
||||
// We're in business.
|
||||
// Find out the size of this variable.
|
||||
size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize()
|
||||
: m_option_watchpoint.watch_size;
|
||||
}
|
||||
type.SetClangType(valobj_sp->GetClangAST(), valobj_sp->GetClangType());
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *error_cstr = error.AsCString(NULL);
|
||||
if (error_cstr)
|
||||
result.GetErrorStream().Printf("error: %s\n", error_cstr);
|
||||
|
@ -1084,10 +1085,12 @@ protected:
|
|||
uint32_t watch_type = m_option_watchpoint.watch_type;
|
||||
error.Clear();
|
||||
Watchpoint *wp = target->CreateWatchpoint(addr, size, &type, watch_type, error).get();
|
||||
if (wp) {
|
||||
if (wp)
|
||||
{
|
||||
wp->SetWatchSpec(command.GetArgumentAtIndex(0));
|
||||
wp->SetWatchVariable(true);
|
||||
if (var_sp && var_sp->GetDeclaration().GetFile()) {
|
||||
if (var_sp && var_sp->GetDeclaration().GetFile())
|
||||
{
|
||||
StreamString ss;
|
||||
// True to show fullpath for declaration file.
|
||||
var_sp->GetDeclaration().DumpStopContext(&ss, true);
|
||||
|
@ -1097,7 +1100,9 @@ protected:
|
|||
wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
|
||||
output_stream.EOL();
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu, variable expression='%s').\n",
|
||||
addr, size, command.GetArgumentAtIndex(0));
|
||||
if (error.AsCString(NULL))
|
||||
|
@ -1135,7 +1140,10 @@ public:
|
|||
"If watchpoint setting fails, consider disable/delete existing ones "
|
||||
"to free up resources.",
|
||||
NULL,
|
||||
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
|
||||
eFlagRequiresFrame |
|
||||
eFlagTryTargetAPILock |
|
||||
eFlagProcessMustBeLaunched |
|
||||
eFlagProcessMustBePaused ),
|
||||
m_option_group (interpreter),
|
||||
m_option_watchpoint ()
|
||||
{
|
||||
|
@ -1182,14 +1190,7 @@ protected:
|
|||
DoExecute (const char *raw_command, CommandReturnObject &result)
|
||||
{
|
||||
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
|
||||
ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
|
||||
StackFrame *frame = exe_ctx.GetFramePtr();
|
||||
if (frame == NULL)
|
||||
{
|
||||
result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint.");
|
||||
result.SetStatus (eReturnStatusFailed);
|
||||
return false;
|
||||
}
|
||||
StackFrame *frame = m_exe_ctx.GetFramePtr();
|
||||
|
||||
Args command(raw_command);
|
||||
|
||||
|
@ -1247,7 +1248,8 @@ protected:
|
|||
frame,
|
||||
valobj_sp,
|
||||
options);
|
||||
if (expr_result != eExecutionCompleted) {
|
||||
if (expr_result != eExecutionCompleted)
|
||||
{
|
||||
result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n");
|
||||
result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str());
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
|
@ -1257,7 +1259,8 @@ protected:
|
|||
// Get the address to watch.
|
||||
bool success = false;
|
||||
addr = valobj_sp->GetValueAsUnsigned(0, &success);
|
||||
if (!success) {
|
||||
if (!success)
|
||||
{
|
||||
result.GetErrorStream().Printf("error: expression did not evaluate to an address\n");
|
||||
result.SetStatus(eReturnStatusFailed);
|
||||
return false;
|
||||
|
@ -1276,8 +1279,10 @@ protected:
|
|||
|
||||
Error error;
|
||||
Watchpoint *wp = target->CreateWatchpoint(addr, size, &type, watch_type, error).get();
|
||||
if (wp) {
|
||||
if (var_sp && var_sp->GetDeclaration().GetFile()) {
|
||||
if (wp)
|
||||
{
|
||||
if (var_sp && var_sp->GetDeclaration().GetFile())
|
||||
{
|
||||
StreamString ss;
|
||||
// True to show fullpath for declaration file.
|
||||
var_sp->GetDeclaration().DumpStopContext(&ss, true);
|
||||
|
@ -1287,7 +1292,9 @@ protected:
|
|||
wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull);
|
||||
output_stream.EOL();
|
||||
result.SetStatus(eReturnStatusSuccessFinishResult);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu).\n",
|
||||
addr, size);
|
||||
if (error.AsCString(NULL))
|
||||
|
|
|
@ -208,8 +208,77 @@ CommandObject::ParseOptions
|
|||
|
||||
|
||||
bool
|
||||
CommandObject::CheckFlags (CommandReturnObject &result)
|
||||
CommandObject::CheckRequirements (CommandReturnObject &result)
|
||||
{
|
||||
#ifdef LLDB_CONFIGURATION_DEBUG
|
||||
// Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx
|
||||
// has shared pointers to the target, process, thread and frame and we don't
|
||||
// want any CommandObject instances to keep any of these objects around
|
||||
// longer than for a single command. Every command should call
|
||||
// CommandObject::Cleanup() after it has completed
|
||||
assert (m_exe_ctx.GetTargetPtr() == NULL);
|
||||
assert (m_exe_ctx.GetProcessPtr() == NULL);
|
||||
assert (m_exe_ctx.GetThreadPtr() == NULL);
|
||||
assert (m_exe_ctx.GetFramePtr() == NULL);
|
||||
#endif
|
||||
|
||||
// Lock down the interpreter's execution context prior to running the
|
||||
// command so we guarantee the selected target, process, thread and frame
|
||||
// can't go away during the execution
|
||||
m_exe_ctx = m_interpreter.GetExecutionContext();
|
||||
|
||||
const uint32_t flags = GetFlags().Get();
|
||||
if (flags & (eFlagRequiresTarget |
|
||||
eFlagRequiresProcess |
|
||||
eFlagRequiresThread |
|
||||
eFlagRequiresFrame |
|
||||
eFlagTryTargetAPILock ))
|
||||
{
|
||||
|
||||
if ((flags & eFlagRequiresTarget) && !m_exe_ctx.HasTargetScope())
|
||||
{
|
||||
result.AppendError (GetInvalidTargetDescription());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((flags & eFlagRequiresProcess) && !m_exe_ctx.HasProcessScope())
|
||||
{
|
||||
result.AppendError (GetInvalidProcessDescription());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((flags & eFlagRequiresThread) && !m_exe_ctx.HasThreadScope())
|
||||
{
|
||||
result.AppendError (GetInvalidThreadDescription());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((flags & eFlagRequiresFrame) && !m_exe_ctx.HasFrameScope())
|
||||
{
|
||||
result.AppendError (GetInvalidFrameDescription());
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((flags & eFlagRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == NULL))
|
||||
{
|
||||
result.AppendError (GetInvalidRegContextDescription());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (flags & eFlagTryTargetAPILock)
|
||||
{
|
||||
Target *target = m_exe_ctx.GetTargetPtr();
|
||||
if (target)
|
||||
{
|
||||
if (m_api_locker.TryLock (target->GetAPIMutex(), NULL) == false)
|
||||
{
|
||||
result.AppendError ("failed to get API lock");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
|
||||
{
|
||||
Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
|
||||
|
@ -263,6 +332,14 @@ CommandObject::CheckFlags (CommandReturnObject &result)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CommandObject::Cleanup ()
|
||||
{
|
||||
m_exe_ctx.Clear();
|
||||
m_api_locker.Unlock();
|
||||
}
|
||||
|
||||
|
||||
class CommandDictCommandPartialMatch
|
||||
{
|
||||
public:
|
||||
|
@ -888,14 +965,16 @@ CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &resu
|
|||
cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
|
||||
}
|
||||
|
||||
if (!CheckFlags(result))
|
||||
return false;
|
||||
|
||||
if (!ParseOptions (cmd_args, result))
|
||||
return false;
|
||||
if (CheckRequirements(result))
|
||||
{
|
||||
if (ParseOptions (cmd_args, result))
|
||||
{
|
||||
// Call the command-specific version of 'Execute', passing it the already processed arguments.
|
||||
handled = DoExecute (cmd_args, result);
|
||||
}
|
||||
}
|
||||
|
||||
// Call the command-specific version of 'Execute', passing it the already processed arguments.
|
||||
handled = DoExecute (cmd_args, result);
|
||||
Cleanup();
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
@ -916,10 +995,10 @@ CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result)
|
|||
}
|
||||
if (!handled)
|
||||
{
|
||||
if (!CheckFlags(result))
|
||||
return false;
|
||||
else
|
||||
if (CheckRequirements(result))
|
||||
handled = DoExecute (args_string, result);
|
||||
|
||||
Cleanup();
|
||||
}
|
||||
return handled;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue