summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/API/SBThread.h3
-rw-r--r--lldb/include/lldb/Core/ValueObject.h21
-rw-r--r--lldb/include/lldb/Core/ValueObjectConstResult.h11
-rw-r--r--lldb/include/lldb/Target/ABI.h4
-rw-r--r--lldb/include/lldb/Target/StopInfo.h5
-rw-r--r--lldb/include/lldb/Target/Thread.h12
-rw-r--r--lldb/include/lldb/Target/ThreadPlan.h6
-rw-r--r--lldb/include/lldb/Target/ThreadPlanStepOut.h10
-rw-r--r--lldb/scripts/Python/interface/SBThread.i3
-rw-r--r--lldb/source/API/SBThread.cpp28
-rw-r--r--lldb/source/API/SBValue.cpp12
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp2
-rw-r--r--lldb/source/Core/Debugger.cpp18
-rw-r--r--lldb/source/Core/ValueObject.cpp70
-rw-r--r--lldb/source/Core/ValueObjectConstResult.cpp24
-rw-r--r--lldb/source/Core/ValueObjectConstResultImpl.cpp2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp2
-rw-r--r--lldb/source/Target/ABI.cpp29
-rw-r--r--lldb/source/Target/StopInfo.cpp28
-rw-r--r--lldb/source/Target/Thread.cpp18
-rw-r--r--lldb/source/Target/ThreadPlanStepOut.cpp47
-rwxr-xr-xlldb/www/formats.html1
22 files changed, 316 insertions, 40 deletions
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index 57a62e1fafa..fb721fe7e1d 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -63,6 +63,9 @@ public:
size_t
GetStopDescription (char *dst, size_t dst_len);
+
+ SBValue
+ GetStopReturnValue ();
lldb::tid_t
GetThreadID () const;
diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h
index 1472ca3b435..d119a65481c 100644
--- a/lldb/include/lldb/Core/ValueObject.h
+++ b/lldb/include/lldb/Core/ValueObject.h
@@ -336,7 +336,7 @@ public:
};
- class EvaluationPoint
+ class EvaluationPoint : public ExecutionContextScope
{
public:
@@ -348,9 +348,6 @@ public:
~EvaluationPoint ();
- ExecutionContextScope *
- GetExecutionContextScope ();
-
const lldb::TargetSP &
GetTargetSP () const
{
@@ -443,6 +440,20 @@ public:
}
+ // If this EvaluationPoint is created without a target, then we could have it
+ // hand out a NULL ExecutionContextScope. But then everybody would have to check that before
+ // calling through it, which is annoying. So instead, we make the EvaluationPoint BE an
+ // ExecutionContextScope, and it hands out the right things.
+ virtual Target *CalculateTarget ();
+
+ virtual Process *CalculateProcess ();
+
+ virtual Thread *CalculateThread ();
+
+ virtual StackFrame *CalculateStackFrame ();
+
+ virtual void CalculateExecutionContext (ExecutionContext &exe_ctx);
+
private:
bool
SyncWithProcessState ()
@@ -479,7 +490,7 @@ public:
ExecutionContextScope *
GetExecutionContextScope ()
{
- return m_update_point.GetExecutionContextScope();
+ return &m_update_point;
}
void
diff --git a/lldb/include/lldb/Core/ValueObjectConstResult.h b/lldb/include/lldb/Core/ValueObjectConstResult.h
index ebba0619e4f..54c017c1824 100644
--- a/lldb/include/lldb/Core/ValueObjectConstResult.h
+++ b/lldb/include/lldb/Core/ValueObjectConstResult.h
@@ -59,6 +59,12 @@ public:
AddressType address_type,
uint8_t addr_byte_size);
+ static lldb::ValueObjectSP
+ Create (ExecutionContextScope *exe_scope,
+ clang::ASTContext *clang_ast,
+ Value &value,
+ const ConstString &name);
+
// When an expression fails to evaluate, we return an error
static lldb::ValueObjectSP
Create (ExecutionContextScope *exe_scope,
@@ -181,6 +187,11 @@ private:
uint8_t addr_byte_size);
ValueObjectConstResult (ExecutionContextScope *exe_scope,
+ clang::ASTContext *clang_ast,
+ const Value &value,
+ const ConstString &name);
+
+ ValueObjectConstResult (ExecutionContextScope *exe_scope,
const Error& error);
DISALLOW_COPY_AND_ASSIGN (ValueObjectConstResult);
diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h
index 76ad8ba6a22..a98ab2a1915 100644
--- a/lldb/include/lldb/Target/ABI.h
+++ b/lldb/include/lldb/Target/ABI.h
@@ -48,6 +48,10 @@ public:
virtual bool
GetReturnValue (Thread &thread,
Value &value) const = 0;
+
+ virtual lldb::ValueObjectSP
+ GetReturnValueObject (Thread &thread,
+ ClangASTType &type) const;
virtual bool
CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan) = 0;
diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h
index 6fedf52831f..6711e2329d8 100644
--- a/lldb/include/lldb/Target/StopInfo.h
+++ b/lldb/include/lldb/Target/StopInfo.h
@@ -126,10 +126,13 @@ public:
CreateStopReasonToTrace (Thread &thread);
static lldb::StopInfoSP
- CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan);
+ CreateStopReasonWithPlan (lldb::ThreadPlanSP &plan, lldb::ValueObjectSP return_valobj_sp);
static lldb::StopInfoSP
CreateStopReasonWithException (Thread &thread, const char *description);
+
+ static lldb::ValueObjectSP
+ GetReturnValueObject (lldb::StopInfoSP &stop_info_sp);
protected:
//------------------------------------------------------------------
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 28a8ed4b3a8..ab416ca2ab1 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -604,7 +604,7 @@ private:
public:
//------------------------------------------------------------------
- /// Gets the inner-most plan that was popped off the plan stack in the
+ /// Gets the outer-most plan that was popped off the plan stack in the
/// most recent stop. Useful for printing the stop reason accurately.
///
/// @return
@@ -614,6 +614,16 @@ public:
GetCompletedPlan ();
//------------------------------------------------------------------
+ /// Gets the outer-most return value from the completed plans
+ ///
+ /// @return
+ /// A ValueObjectSP, either empty if there is no return value,
+ /// or containing the return value.
+ //------------------------------------------------------------------
+ lldb::ValueObjectSP
+ GetReturnValueObject ();
+
+ //------------------------------------------------------------------
/// Checks whether the given plan is in the completed plans for this
/// stop.
///
diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h
index d848e54fa40..e31071bc9b9 100644
--- a/lldb/include/lldb/Target/ThreadPlan.h
+++ b/lldb/include/lldb/Target/ThreadPlan.h
@@ -387,6 +387,12 @@ public:
return m_thread.GetStopInfo ();
}
+ virtual lldb::ValueObjectSP
+ GetReturnValueObject ()
+ {
+ return lldb::ValueObjectSP();
+ }
+
protected:
//------------------------------------------------------------------
// Classes that inherit from ThreadPlan can see and modify these
diff --git a/lldb/include/lldb/Target/ThreadPlanStepOut.h b/lldb/include/lldb/Target/ThreadPlanStepOut.h
index c2273db81e7..b96be5d29a3 100644
--- a/lldb/include/lldb/Target/ThreadPlanStepOut.h
+++ b/lldb/include/lldb/Target/ThreadPlanStepOut.h
@@ -42,6 +42,11 @@ public:
virtual bool WillStop ();
virtual bool MischiefManaged ();
virtual void DidPush();
+
+ virtual lldb::ValueObjectSP GetReturnValueObject()
+ {
+ return m_return_valobj_sp;
+ }
protected:
bool QueueInlinedStepPlan (bool queue_now);
@@ -56,6 +61,8 @@ private:
bool m_stop_others;
lldb::ThreadPlanSP m_step_through_inline_plan_sp;
lldb::ThreadPlanSP m_step_out_plan_sp;
+ Function *m_immediate_step_from_function;
+ lldb::ValueObjectSP m_return_valobj_sp;
friend ThreadPlan *
Thread::QueueThreadPlanForStepOut (bool abort_other_plans,
@@ -69,6 +76,9 @@ private:
// Need an appropriate marker for the current stack so we can tell step out
// from step in.
+ void
+ CalculateReturnValue();
+
DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOut);
};
diff --git a/lldb/scripts/Python/interface/SBThread.i b/lldb/scripts/Python/interface/SBThread.i
index 67170908954..413d16c1f3f 100644
--- a/lldb/scripts/Python/interface/SBThread.i
+++ b/lldb/scripts/Python/interface/SBThread.i
@@ -82,6 +82,9 @@ public:
size_t
GetStopDescription (char *dst, size_t dst_len);
+ SBValue
+ GetStopReturnValue ();
+
lldb::tid_t
GetThreadID () const;
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp
index 69924ad6ad0..9ea28772978 100644
--- a/lldb/source/API/SBThread.cpp
+++ b/lldb/source/API/SBThread.cpp
@@ -31,10 +31,10 @@
#include "lldb/API/SBAddress.h"
-#include "lldb/API/SBFrame.h"
-// DONT THINK THIS IS NECESSARY: #include "lldb/API/SBSourceManager.h"
#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBFrame.h"
#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBValue.h"
using namespace lldb;
using namespace lldb_private;
@@ -316,6 +316,30 @@ SBThread::GetStopDescription (char *dst, size_t dst_len)
return 0;
}
+SBValue
+SBThread::GetStopReturnValue ()
+{
+ ValueObjectSP return_valobj_sp;
+ if (m_opaque_sp)
+ {
+ Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex());
+ StopInfoSP stop_info_sp = m_opaque_sp->GetStopInfo ();
+ if (stop_info_sp)
+ {
+ return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
+ }
+ }
+
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ if (log)
+ log->Printf ("SBThread(%p)::GetStopReturnValue () => %s", m_opaque_sp.get(),
+ return_valobj_sp.get()
+ ? return_valobj_sp->GetValueAsCString()
+ : "<no return value>");
+
+ return SBValue (return_valobj_sp);
+}
+
void
SBThread::SetThread (const ThreadSP& lldb_object_sp)
{
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index c9f78e2cf1f..daaeea089ca 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -380,7 +380,7 @@ SBValue::CreateValueFromExpression (const char *name, const char* expression)
{
ValueObjectSP result_valobj_sp;
m_opaque_sp->GetUpdatePoint().GetTargetSP()->EvaluateExpression (expression,
- m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame(),
+ m_opaque_sp->GetExecutionContextScope()->CalculateStackFrame(),
eExecutionPolicyOnlyWhenNeeded,
true, // unwind on error
true, // keep in memory
@@ -410,7 +410,7 @@ SBValue::CreateValueFromAddress(const char* name, lldb::addr_t address, SBType t
lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t)));
- ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope(),
+ ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (m_opaque_sp->GetExecutionContextScope(),
real_type.m_opaque_sp->GetASTContext(),
real_type.m_opaque_sp->GetOpaqueQualType(),
ConstString(name),
@@ -871,9 +871,9 @@ SBValue::GetThread()
SBThread result;
if (m_opaque_sp)
{
- if (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope())
+ if (m_opaque_sp->GetExecutionContextScope())
{
- result = SBThread(m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateThread()->GetSP());
+ result = SBThread(m_opaque_sp->GetExecutionContextScope()->CalculateThread()->GetSP());
}
}
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
@@ -893,9 +893,9 @@ SBValue::GetFrame()
SBFrame result;
if (m_opaque_sp)
{
- if (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope())
+ if (m_opaque_sp->GetExecutionContextScope())
{
- result.SetFrame (m_opaque_sp->GetUpdatePoint().GetExecutionContextScope()->CalculateStackFrame()->GetSP());
+ result.SetFrame (m_opaque_sp->GetExecutionContextScope()->CalculateStackFrame()->GetSP());
}
}
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 658222e19d8..d6a9670fe0f 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -1246,7 +1246,7 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread (CommandInterpreter &
LoadSubCommand ("step-out", CommandObjectSP (new CommandObjectThreadStepWithTypeAndScope (
interpreter,
"thread step-out",
- "Finish executing the current function 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,
eFlagProcessMustBeLaunched | eFlagProcessMustBePaused,
eStepTypeOut,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index cd86698661a..e33e9412c91 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -1701,6 +1701,23 @@ Debugger::FormatPrompt
}
}
}
+ else if (::strncmp (var_name_begin, "return-value}", strlen("return-value}")) == 0)
+ {
+ StopInfoSP stop_info_sp = thread->GetStopInfo ();
+ if (stop_info_sp)
+ {
+ ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp);
+ if (return_valobj_sp)
+ {
+ cstr = return_valobj_sp->GetValueAsCString ();
+ if (cstr && cstr[0])
+ {
+ s.PutCString(cstr);
+ var_success = true;
+ }
+ }
+ }
+ }
}
}
}
@@ -2562,6 +2579,7 @@ Debugger::SettingsController::global_settings_table[] =
MODULE_WITH_FUNC\
FILE_AND_LINE\
"{, stop reason = ${thread.stop-reason}}"\
+ "{, return value = ${thread.return-value}}"\
"\\n"
//#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id}"\
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index 657faf36f85..e1c25becbc7 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -707,7 +707,7 @@ ValueObject::GetPointeeData (DataExtractor& data,
AddressType addr_type;
lldb::addr_t addr = IsPointerType() ? GetPointerValue(&addr_type) : GetAddressOf(true, &addr_type);
- ExecutionContextScope *exe_scope = m_update_point.GetExecutionContextScope();
+ ExecutionContextScope *exe_scope = GetExecutionContextScope();
switch (addr_type)
@@ -3428,12 +3428,14 @@ ValueObject::CastPointerType (const char *name, TypeSP &type_sp)
}
ValueObject::EvaluationPoint::EvaluationPoint () :
+ ExecutionContextScope(),
m_thread_id (LLDB_INVALID_UID),
m_mod_id ()
{
}
ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected):
+ ExecutionContextScope (),
m_needs_update (true),
m_first_update (true),
m_thread_id (LLDB_INVALID_THREAD_ID),
@@ -3500,14 +3502,47 @@ ValueObject::EvaluationPoint::~EvaluationPoint ()
{
}
-ExecutionContextScope *
-ValueObject::EvaluationPoint::GetExecutionContextScope ()
+Target *
+ValueObject::EvaluationPoint::CalculateTarget ()
{
- // We have to update before giving out the scope, or we could be handing out stale pointers.
- ExecutionContextScope *exe_scope;
+ return m_target_sp.get();
+}
+
+Process *
+ValueObject::EvaluationPoint::CalculateProcess ()
+{
+ return m_process_sp.get();
+}
+
+Thread *
+ValueObject::EvaluationPoint::CalculateThread ()
+{
+ ExecutionContextScope *exe_scope;
SyncWithProcessState(exe_scope);
-
- return exe_scope;
+ if (exe_scope)
+ return exe_scope->CalculateThread();
+ else
+ return NULL;
+}
+
+StackFrame *
+ValueObject::EvaluationPoint::CalculateStackFrame ()
+{
+ ExecutionContextScope *exe_scope;
+ SyncWithProcessState(exe_scope);
+ if (exe_scope)
+ return exe_scope->CalculateStackFrame();
+ else
+ return NULL;
+}
+
+void
+ValueObject::EvaluationPoint::CalculateExecutionContext (ExecutionContext &exe_ctx)
+{
+ ExecutionContextScope *exe_scope;
+ SyncWithProcessState(exe_scope);
+ if (exe_scope)
+ return exe_scope->CalculateExecutionContext (exe_ctx);
}
// This function checks the EvaluationPoint against the current process state. If the current
@@ -3520,12 +3555,18 @@ ValueObject::EvaluationPoint::GetExecutionContextScope ()
bool
ValueObject::EvaluationPoint::SyncWithProcessState(ExecutionContextScope *&exe_scope)
{
+
+ // Start with the target, if it is NULL, then we're obviously not going to get any further:
+ exe_scope = m_target_sp.get();
+
+ if (exe_scope == NULL)
+ return false;
+
// If we don't have a process nothing can change.
if (!m_process_sp)
- {
- exe_scope = m_target_sp.get();
return false;
- }
+
+ exe_scope = m_process_sp.get();
// If our stop id is the current stop ID, nothing has changed:
ProcessModID current_mod_id = m_process_sp->GetModID();
@@ -3533,10 +3574,7 @@ ValueObject::EvaluationPoint::SyncWithProcessState(ExecutionContextScope *&exe_s
// If the current stop id is 0, either we haven't run yet, or the process state has been cleared.
// In either case, we aren't going to be able to sync with the process state.
if (current_mod_id.GetStopID() == 0)
- {
- exe_scope = m_target_sp.get();
return false;
- }
bool changed;
@@ -3555,10 +3593,10 @@ ValueObject::EvaluationPoint::SyncWithProcessState(ExecutionContextScope *&exe_s
changed = true;
}
}
- exe_scope = m_process_sp.get();
- // Something has changed, so we will return true. Now make sure the thread & frame still exist, and if either
- // doesn't, mark ourselves as invalid.
+ // Now re-look up the thread and frame in case the underlying objects have gone away & been recreated.
+ // That way we'll be sure to return a valid exe_scope.
+ // If we used to have a thread or a frame but can't find it anymore, then mark ourselves as invalid.
if (m_thread_id != LLDB_INVALID_THREAD_ID)
{
diff --git a/lldb/source/Core/ValueObjectConstResult.cpp b/lldb/source/Core/ValueObjectConstResult.cpp
index fa1503f3217..950d33405af 100644
--- a/lldb/source/Core/ValueObjectConstResult.cpp
+++ b/lldb/source/Core/ValueObjectConstResult.cpp
@@ -130,6 +130,15 @@ ValueObjectConstResult::Create
address))->GetSP();
}
+ValueObjectSP
+ValueObjectConstResult::Create (ExecutionContextScope *exe_scope,
+ clang::ASTContext *clang_ast,
+ Value &value,
+ const ConstString &name)
+{
+ return (new ValueObjectConstResult (exe_scope, clang_ast, value, name))->GetSP();
+}
+
ValueObjectConstResult::ValueObjectConstResult
(
ExecutionContextScope *exe_scope,
@@ -239,6 +248,21 @@ ValueObjectConstResult::ValueObjectConstResult (
SetIsConstant ();
}
+ValueObjectConstResult::ValueObjectConstResult (
+ ExecutionContextScope *exe_scope,
+ clang::ASTContext *clang_ast,
+ const Value &value,
+ const ConstString &name) :
+ ValueObject (exe_scope),
+ m_type_name (),
+ m_byte_size (0),
+ m_clang_ast (clang_ast),
+ m_impl(this)
+{
+ m_value = value;
+ m_value.GetData(m_data);
+}
+
ValueObjectConstResult::~ValueObjectConstResult()
{
}
diff --git a/lldb/source/Core/ValueObjectConstResultImpl.cpp b/lldb/source/Core/ValueObjectConstResultImpl.cpp
index afe050291b0..31646b4ca0b 100644
--- a/lldb/source/Core/ValueObjectConstResultImpl.cpp
+++ b/lldb/source/Core/ValueObjectConstResultImpl.cpp
@@ -185,7 +185,7 @@ ValueObjectConstResultImpl::AddressOf (Error &error)
std::string new_name("&");
new_name.append(m_impl_backend->GetName().AsCString(""));
- m_address_of_backend = ValueObjectConstResult::Create(m_impl_backend->GetUpdatePoint().GetExecutionContextScope(),
+ m_address_of_backend = ValueObjectConstResult::Create(m_impl_backend->GetExecutionContextScope(),
type.GetASTContext(),
type.GetPointerType(),
ConstString(new_name.c_str()),
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 4119c6e5273..1094dc1e34c 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -309,7 +309,7 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
// If the class address didn't point into the binary, or
// it points into the right section but there wasn't a symbol
// there, try to look it up by calling the class method in the target.
- ExecutionContextScope *exe_scope = in_value.GetUpdatePoint().GetExecutionContextScope();
+ ExecutionContextScope *exe_scope = in_value.GetExecutionContextScope();
Thread *thread_to_use;
if (exe_scope)
thread_to_use = exe_scope->CalculateThread();
diff --git a/lldb/source/Target/ABI.cpp b/lldb/source/Target/ABI.cpp
index fc55ccac6fc..f3a5404aa10 100644
--- a/lldb/source/Target/ABI.cpp
+++ b/lldb/source/Target/ABI.cpp
@@ -9,6 +9,10 @@
#include "lldb/Target/ABI.h"
#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Symbol/ClangASTType.h"
+#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
@@ -97,3 +101,28 @@ ABI::GetRegisterInfoByKind (RegisterKind reg_kind, uint32_t reg_num, RegisterInf
}
return false;
}
+
+ValueObjectSP
+ABI::GetReturnValueObject (Thread &thread,
+ ClangASTType &ast_type) const
+{
+ if (!ast_type.IsValid())
+ return ValueObjectSP();
+
+ Value ret_value;
+ ret_value.SetContext(Value::eContextTypeClangType,
+ ast_type.GetOpaqueQualType());
+ if (GetReturnValue (thread, ret_value))
+ {
+ return ValueObjectConstResult::Create(
+ thread.GetStackFrameAtIndex(0).get(),
+ ast_type.GetASTContext(),
+ ret_value,
+ ConstString("FunctionReturn"));
+
+ }
+ else
+ return ValueObjectSP();
+}
+
+
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 4e089d42c05..f90968fdad7 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -722,9 +722,10 @@ class StopInfoThreadPlan : public StopInfo
{
public:
- StopInfoThreadPlan (ThreadPlanSP &plan_sp) :
+ StopInfoThreadPlan (ThreadPlanSP &plan_sp, ValueObjectSP &return_valobj_sp) :
StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
- m_plan_sp (plan_sp)
+ m_plan_sp (plan_sp),
+ m_return_valobj_sp (return_valobj_sp)
{
}
@@ -749,9 +750,16 @@ public:
}
return m_description.c_str();
}
+
+ ValueObjectSP
+ GetReturnValueObject()
+ {
+ return m_return_valobj_sp;
+ }
private:
ThreadPlanSP m_plan_sp;
+ ValueObjectSP m_return_valobj_sp;
};
} // namespace lldb_private
@@ -786,9 +794,9 @@ StopInfo::CreateStopReasonToTrace (Thread &thread)
}
StopInfoSP
-StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp)
+StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp, ValueObjectSP return_valobj_sp)
{
- return StopInfoSP (new StopInfoThreadPlan (plan_sp));
+ return StopInfoSP (new StopInfoThreadPlan (plan_sp, return_valobj_sp));
}
StopInfoSP
@@ -796,3 +804,15 @@ StopInfo::CreateStopReasonWithException (Thread &thread, const char *description
{
return StopInfoSP (new StopInfoException (thread, description));
}
+
+ValueObjectSP
+StopInfo::GetReturnValueObject(StopInfoSP &stop_info_sp)
+{
+ if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonPlanComplete)
+ {
+ StopInfoThreadPlan *plan_stop_info = static_cast<StopInfoThreadPlan *>(stop_info_sp.get());
+ return plan_stop_info->GetReturnValueObject();
+ }
+ else
+ return ValueObjectSP();
+}
diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp
index e4415b7b73e..6fe6ec7df5b 100644
--- a/lldb/source/Target/Thread.cpp
+++ b/lldb/source/Target/Thread.cpp
@@ -95,7 +95,7 @@ Thread::GetStopInfo ()
{
ThreadPlanSP plan_sp (GetCompletedPlan());
if (plan_sp)
- return StopInfo::CreateStopReasonWithPlan (plan_sp);
+ return StopInfo::CreateStopReasonWithPlan (plan_sp, GetReturnValueObject());
else
{
if (m_actual_stop_info_sp
@@ -551,6 +551,22 @@ Thread::GetCompletedPlan ()
return empty_plan_sp;
}
+ValueObjectSP
+Thread::GetReturnValueObject ()
+{
+ if (!m_completed_plan_stack.empty())
+ {
+ for (int i = m_completed_plan_stack.size() - 1; i >= 0; i--)
+ {
+ ValueObjectSP return_valobj_sp;
+ return_valobj_sp = m_completed_plan_stack[i]->GetReturnValueObject();
+ if (return_valobj_sp)
+ return return_valobj_sp;
+ }
+ }
+ return ValueObjectSP();
+}
+
bool
Thread::IsThreadPlanDone (ThreadPlan *plan)
{
diff --git a/lldb/source/Target/ThreadPlanStepOut.cpp b/lldb/source/Target/ThreadPlanStepOut.cpp
index d78411ee936..485db25dd8d 100644
--- a/lldb/source/Target/ThreadPlanStepOut.cpp
+++ b/lldb/source/Target/ThreadPlanStepOut.cpp
@@ -16,6 +16,8 @@
#include "lldb/Breakpoint/Breakpoint.h"
#include "lldb/lldb-private-log.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
@@ -47,7 +49,8 @@ ThreadPlanStepOut::ThreadPlanStepOut
m_first_insn (first_insn),
m_stop_others (stop_others),
m_step_through_inline_plan_sp(),
- m_step_out_plan_sp ()
+ m_step_out_plan_sp (),
+ m_immediate_step_from_function(NULL)
{
m_step_from_insn = m_thread.GetRegisterContext()->GetPC(0);
@@ -88,6 +91,15 @@ ThreadPlanStepOut::ThreadPlanStepOut
return_bp->SetThreadID(m_thread.GetID());
m_return_bp_id = return_bp->GetID();
}
+
+ if (immediate_return_from_sp)
+ {
+ const SymbolContext &sc = immediate_return_from_sp->GetSymbolContext(eSymbolContextFunction);
+ if (sc.function)
+ {
+ m_immediate_step_from_function = sc.function;
+ }
+ }
}
}
@@ -152,6 +164,7 @@ ThreadPlanStepOut::PlanExplainsStop ()
if (m_step_out_plan_sp->MischiefManaged())
{
// If this one is done, then we are all done.
+ CalculateReturnValue();
SetPlanComplete();
return true;
}
@@ -183,7 +196,10 @@ ThreadPlanStepOut::PlanExplainsStop ()
{
const uint32_t num_frames = m_thread.GetStackFrameCount();
if (m_stack_depth > num_frames)
+ {
+ CalculateReturnValue();
SetPlanComplete();
+ }
// If there was only one owner, then we're done. But if we also hit some
// user breakpoint on our way out, we should mark ourselves as done, but
@@ -217,6 +233,7 @@ ThreadPlanStepOut::ShouldStop (Event *event_ptr)
}
else if (m_stack_depth > m_thread.GetStackFrameCount())
{
+ CalculateReturnValue();
SetPlanComplete();
return true;
}
@@ -233,6 +250,7 @@ ThreadPlanStepOut::ShouldStop (Event *event_ptr)
}
else
{
+ CalculateReturnValue();
SetPlanComplete ();
return true;
}
@@ -244,6 +262,10 @@ ThreadPlanStepOut::ShouldStop (Event *event_ptr)
{
if (m_step_through_inline_plan_sp->MischiefManaged())
{
+ // We don't calculate the return value here because we don't know how to.
+ // But in case we had a return value sitting around from our process in
+ // getting here, let's clear it out.
+ m_return_valobj_sp.reset();
SetPlanComplete();
return true;
}
@@ -387,3 +409,26 @@ ThreadPlanStepOut::QueueInlinedStepPlan (bool queue_now)
return false;
}
+
+void
+ThreadPlanStepOut::CalculateReturnValue ()
+{
+ if (m_return_valobj_sp)
+ return;
+
+ if (m_immediate_step_from_function != NULL)
+ {
+ Type *return_type = m_immediate_step_from_function->GetType();
+ lldb::clang_type_t return_clang_type = m_immediate_step_from_function->GetReturnClangType();
+ if (return_type && return_clang_type)
+ {
+ ClangASTType ast_type (return_type->GetClangAST(), return_clang_type);
+
+ lldb::ABISP abi_sp = m_thread.GetProcess().GetABI();
+ if (abi_sp)
+ {
+ m_return_valobj_sp = abi_sp->GetReturnValueObject(m_thread, ast_type);
+ }
+ }
+ }
+}
diff --git a/lldb/www/formats.html b/lldb/www/formats.html
index ff5dc8dd396..7c81359cf3c 100755
--- a/lldb/www/formats.html
+++ b/lldb/www/formats.html
@@ -97,6 +97,7 @@
<tr valign=top><td><b>thread.name</b></td><td>The name of the thread if the target OS supports naming threads</td></tr>
<tr valign=top><td><b>thread.queue</b></td><td>The queue name of the thread if the target OS supports dispatch queues</td></tr>
<tr valign=top><td><b>thread.stop-reason</b></td><td>A textual reason each thread stopped</td></tr>
+ <tr valign=top><td><b>thread.return-value</b></td><td>The return value of the latest step operation (currently only for step-out.)</td></tr>
<tr valign=top><td><b>target.arch</b></td><td>The architecture of the current target</td></tr>
</table>
OpenPOWER on IntegriCloud