[Lldb-commits] [lldb] r163867 - in /lldb/trunk: include/lldb/API/SBThread.h include/lldb/Target/RegisterContext.h include/lldb/Target/Thread.h scripts/Python/interface/SBThread.i source/API/SBThread.cpp source/Commands/CommandObjectThread.cpp source/Target/RegisterContext.cpp source/Target/Thread.cpp
Jim Ingham
jingham at apple.com
Thu Sep 13 19:14:15 PDT 2012
Author: jingham
Date: Thu Sep 13 21:14:15 2012
New Revision: 163867
URL: http://llvm.org/viewvc/llvm-project?rev=163867&view=rev
Log:
Make the unwinding of the stack part of "thread return" work, and add the thread return command.
Modified:
lldb/trunk/include/lldb/API/SBThread.h
lldb/trunk/include/lldb/Target/RegisterContext.h
lldb/trunk/include/lldb/Target/Thread.h
lldb/trunk/scripts/Python/interface/SBThread.i
lldb/trunk/source/API/SBThread.cpp
lldb/trunk/source/Commands/CommandObjectThread.cpp
lldb/trunk/source/Target/RegisterContext.cpp
lldb/trunk/source/Target/Thread.cpp
Modified: lldb/trunk/include/lldb/API/SBThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBThread.h?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBThread.h (original)
+++ lldb/trunk/include/lldb/API/SBThread.h Thu Sep 13 21:14:15 2012
@@ -103,7 +103,7 @@
RunToAddress (lldb::addr_t addr);
SBError
- ReturnToFrame (SBFrame &frame, SBValue &return_value);
+ ReturnFromFrame (SBFrame &frame, SBValue &return_value);
//--------------------------------------------------------------------------
/// LLDB currently supports process centric debugging which means when any
Modified: lldb/trunk/include/lldb/Target/RegisterContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/RegisterContext.h?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/RegisterContext.h (original)
+++ lldb/trunk/include/lldb/Target/RegisterContext.h Thu Sep 13 21:14:15 2012
@@ -72,6 +72,9 @@
virtual bool
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0;
+ bool
+ CopyFromRegisterContext (lldb::RegisterContextSP context);
+
virtual uint32_t
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) = 0;
Modified: lldb/trunk/include/lldb/Target/Thread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Thread.h?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Thread.h (original)
+++ lldb/trunk/include/lldb/Target/Thread.h Thu Sep 13 21:14:15 2012
@@ -286,10 +286,10 @@
}
Error
- ReturnToFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp);
+ ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp);
Error
- ReturnToFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp);
+ ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp);
virtual lldb::StackFrameSP
GetFrameWithStackID (const StackID &stack_id)
Modified: lldb/trunk/scripts/Python/interface/SBThread.i
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/scripts/Python/interface/SBThread.i?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/scripts/Python/interface/SBThread.i (original)
+++ lldb/trunk/scripts/Python/interface/SBThread.i Thu Sep 13 21:14:15 2012
@@ -131,7 +131,7 @@
RunToAddress (lldb::addr_t addr);
SBError
- ReturnToFrame (SBFrame &frame, SBValue &return_value);
+ ReturnFromFrame (SBFrame &frame, SBValue &return_value);
%feature("docstring", "
//--------------------------------------------------------------------------
Modified: lldb/trunk/source/API/SBThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBThread.cpp?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/source/API/SBThread.cpp (original)
+++ lldb/trunk/source/API/SBThread.cpp Thu Sep 13 21:14:15 2012
@@ -878,7 +878,7 @@
}
SBError
-SBThread::ReturnToFrame (SBFrame &frame, SBValue &return_value)
+SBThread::ReturnFromFrame (SBFrame &frame, SBValue &return_value)
{
SBError sb_error;
@@ -889,12 +889,12 @@
if (log)
- log->Printf ("SBThread(%p)::ReturnToFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID());
+ log->Printf ("SBThread(%p)::ReturnFromFrame (frame=%d)", exe_ctx.GetThreadPtr(), frame.GetFrameID());
if (exe_ctx.HasThreadScope())
{
Thread *thread = exe_ctx.GetThreadPtr();
- sb_error.SetError (thread->ReturnToFrame(frame.GetFrameSP(), return_value.GetSP()));
+ sb_error.SetError (thread->ReturnFromFrame(frame.GetFrameSP(), return_value.GetSP()));
}
return sb_error;
Modified: lldb/trunk/source/Commands/CommandObjectThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectThread.cpp?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectThread.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectThread.cpp Thu Sep 13 21:14:15 2012
@@ -13,6 +13,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
+#include "lldb/lldb-private.h"
#include "lldb/Core/State.h"
#include "lldb/Core/SourceManager.h"
#include "lldb/Host/Host.h"
@@ -1244,6 +1245,107 @@
}
};
+class CommandObjectThreadReturn : public CommandObjectRaw
+{
+public:
+ CommandObjectThreadReturn (CommandInterpreter &interpreter) :
+ CommandObjectRaw (interpreter,
+ "thread return",
+ "Return from the currently selected frame, short-circuiting execution of the frames below it, with an optional return value.",
+ "thread return",
+ eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
+ {
+ CommandArgumentEntry arg;
+ CommandArgumentData expression_arg;
+
+ // Define the first (and only) variant of this arg.
+ expression_arg.arg_type = eArgTypeExpression;
+ expression_arg.arg_repetition = eArgRepeatPlain;
+
+ // There is only one variant this argument could be; put it into the argument entry.
+ arg.push_back (expression_arg);
+
+ // Push the data for the first argument into the m_arguments vector.
+ m_arguments.push_back (arg);
+
+
+ }
+
+ ~CommandObjectThreadReturn()
+ {
+ }
+
+protected:
+
+ bool DoExecute
+ (
+ const char *command,
+ CommandReturnObject &result
+ )
+ {
+ // If there is a command string, pass it to the expression parser:
+ ExecutionContext exe_ctx = m_interpreter.GetExecutionContext();
+ if (!(exe_ctx.HasProcessScope() && exe_ctx.HasThreadScope() && exe_ctx.HasFrameScope()))
+ {
+ result.AppendError("Must have selected process, thread and frame for thread return.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ ValueObjectSP return_valobj_sp;
+
+ StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+ uint32_t frame_idx = frame_sp->GetFrameIndex();
+
+ if (frame_sp->IsInlined())
+ {
+ result.AppendError("Don't know how to return from inlined frames.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ if (command && command[0] != '\0')
+ {
+ Target *target = exe_ctx.GetTargetPtr();
+ Target::EvaluateExpressionOptions options;
+
+ options.SetUnwindOnError(true);
+ options.SetUseDynamic(eNoDynamicValues);
+
+ ExecutionResults exe_results = eExecutionSetupError;
+ exe_results = target->EvaluateExpression (command,
+ frame_sp.get(),
+ return_valobj_sp,
+ options);
+ if (exe_results != eExecutionCompleted)
+ {
+ if (return_valobj_sp)
+ result.AppendErrorWithFormat("Error evaluating result expression: %s", return_valobj_sp->GetError().AsCString());
+ else
+ result.AppendErrorWithFormat("Unknown error evaluating result expression.");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+
+ }
+ }
+
+ Error error;
+ ThreadSP thread_sp = exe_ctx.GetThreadSP();
+ error = thread_sp->ReturnFromFrame (frame_sp, return_valobj_sp);
+ if (!error.Success())
+ {
+ result.AppendErrorWithFormat("Error returning from frame %d of thread %d: %s.", frame_idx, thread_sp->GetIndexID(), error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+
+ thread_sp->GetStatus(result.GetOutputStream(), 0, 1, 1);
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+ return true;
+ }
+
+};
+
//-------------------------------------------------------------------------
// CommandObjectMultiwordThread
//-------------------------------------------------------------------------
@@ -1257,6 +1359,7 @@
LoadSubCommand ("backtrace", CommandObjectSP (new CommandObjectThreadBacktrace (interpreter)));
LoadSubCommand ("continue", CommandObjectSP (new CommandObjectThreadContinue (interpreter)));
LoadSubCommand ("list", CommandObjectSP (new CommandObjectThreadList (interpreter)));
+ LoadSubCommand ("return", CommandObjectSP (new CommandObjectThreadReturn (interpreter)));
LoadSubCommand ("select", CommandObjectSP (new CommandObjectThreadSelect (interpreter)));
LoadSubCommand ("until", CommandObjectSP (new CommandObjectThreadUntil (interpreter)));
LoadSubCommand ("step-in", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
Modified: lldb/trunk/source/Target/RegisterContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/RegisterContext.cpp?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/source/Target/RegisterContext.cpp (original)
+++ lldb/trunk/source/Target/RegisterContext.cpp Thu Sep 13 21:14:15 2012
@@ -196,6 +196,47 @@
return false;
}
+bool
+RegisterContext::CopyFromRegisterContext (lldb::RegisterContextSP context)
+{
+ uint32_t num_register_sets = context->GetRegisterSetCount();
+ // We don't know that two threads have the same register context, so require the threads to be the same.
+ if (context->GetThreadID() != GetThreadID())
+ return false;
+
+ if (num_register_sets != GetRegisterSetCount())
+ return false;
+
+ RegisterContextSP frame_zero_context = m_thread.GetRegisterContext();
+
+ for (uint32_t set_idx = 0; set_idx < num_register_sets; ++set_idx)
+ {
+ const RegisterSet * const reg_set = GetRegisterSet(set_idx);
+
+ const uint32_t num_registers = reg_set->num_registers;
+ for (uint32_t reg_idx = 0; reg_idx < num_registers; ++reg_idx)
+ {
+ const uint32_t reg = reg_set->registers[reg_idx];
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+ if (!reg_info || reg_info->value_regs)
+ continue;
+ RegisterValue reg_value;
+
+ // If we can reconstruct the register from the frame we are copying from, then do so, otherwise
+ // use the value from frame 0.
+ if (context->ReadRegister(reg_info, reg_value))
+ {
+ WriteRegister(reg_info, reg_value);
+ }
+ else if (frame_zero_context->ReadRegister(reg_info, reg_value))
+ {
+ WriteRegister(reg_info, reg_value);
+ }
+ }
+ }
+ return true;
+}
+
lldb::tid_t
RegisterContext::GetThreadID() const
{
Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=163867&r1=163866&r2=163867&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Thu Sep 13 21:14:15 2012
@@ -1273,7 +1273,7 @@
Error
-Thread::ReturnToFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp)
+Thread::ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp)
{
StackFrameSP frame_sp = GetStackFrameAtIndex (frame_idx);
Error return_error;
@@ -1283,11 +1283,11 @@
return_error.SetErrorStringWithFormat("Could not find frame with index %d in thread 0x%llx.", frame_idx, GetID());
}
- return ReturnToFrame(frame_sp, return_value_sp);
+ return ReturnFromFrame(frame_sp, return_value_sp);
}
Error
-Thread::ReturnToFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp)
+Thread::ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp)
{
Error return_error;
@@ -1298,32 +1298,37 @@
}
Thread *thread = frame_sp->GetThread().get();
+ uint32_t older_frame_idx = frame_sp->GetFrameIndex() + 1;
+ StackFrameSP older_frame_sp = thread->GetStackFrameAtIndex(older_frame_idx);
if (return_value_sp)
{
+ // TODO: coerce the return_value_sp to the type of the function in frame_sp.
+
lldb::ABISP abi = thread->GetProcess()->GetABI();
if (!abi)
{
return_error.SetErrorString("Could not find ABI to set return value.");
}
- return_error = abi->SetReturnValueObject(frame_sp, return_value_sp);
+ return_error = abi->SetReturnValueObject(older_frame_sp, return_value_sp);
if (!return_error.Success())
return return_error;
}
// Now write the return registers for the chosen frame:
- lldb::DataBufferSP register_values_sp;
- frame_sp->GetRegisterContext()->ReadAllRegisterValues (register_values_sp);
- if (thread->ResetFrameZeroRegisters(register_values_sp))
+ // Note, we can't use ReadAllRegisterValues->WriteAllRegisterValues, since the read & write
+ // cook their data
+ bool copy_success = thread->GetStackFrameAtIndex(0)->GetRegisterContext()->CopyFromRegisterContext(older_frame_sp->GetRegisterContext());
+ if (copy_success)
{
thread->DiscardThreadPlans(true);
+ thread->ClearStackFrames();
return return_error;
}
else
{
return_error.SetErrorString("Could not reset register values.");
return return_error;
-
}
}
More information about the lldb-commits
mailing list