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