diff options
| author | Jim Ingham <jingham@apple.com> | 2011-12-17 01:35:57 +0000 |
|---|---|---|
| committer | Jim Ingham <jingham@apple.com> | 2011-12-17 01:35:57 +0000 |
| commit | 73ca05a2a0c6ce957f9679e76b35ee06dc1559d4 (patch) | |
| tree | 20b0f08ba2a6812f994fdea521bf436ea25453ce /lldb/source | |
| parent | 903231bc58b27bbd1b74622b013fa277ceaeb16f (diff) | |
| download | bcm5719-llvm-73ca05a2a0c6ce957f9679e76b35ee06dc1559d4.tar.gz bcm5719-llvm-73ca05a2a0c6ce957f9679e76b35ee06dc1559d4.zip | |
Add the ability to capture the return value in a thread's stop info, and print it
as part of the thread format output.
Currently this is only done for the ThreadPlanStepOut.
Add a convenience API ABI::GetReturnValueObject.
Change the ValueObject::EvaluationPoint to BE an ExecutionContextScope, rather than
trying to hand out one of its subsidiary object's pointers. That way this will always
be good.
llvm-svn: 146806
Diffstat (limited to 'lldb/source')
| -rw-r--r-- | lldb/source/API/SBThread.cpp | 28 | ||||
| -rw-r--r-- | lldb/source/API/SBValue.cpp | 12 | ||||
| -rw-r--r-- | lldb/source/Commands/CommandObjectThread.cpp | 2 | ||||
| -rw-r--r-- | lldb/source/Core/Debugger.cpp | 18 | ||||
| -rw-r--r-- | lldb/source/Core/ValueObject.cpp | 70 | ||||
| -rw-r--r-- | lldb/source/Core/ValueObjectConstResult.cpp | 24 | ||||
| -rw-r--r-- | lldb/source/Core/ValueObjectConstResultImpl.cpp | 2 | ||||
| -rw-r--r-- | lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 2 | ||||
| -rw-r--r-- | lldb/source/Target/ABI.cpp | 29 | ||||
| -rw-r--r-- | lldb/source/Target/StopInfo.cpp | 28 | ||||
| -rw-r--r-- | lldb/source/Target/Thread.cpp | 18 | ||||
| -rw-r--r-- | lldb/source/Target/ThreadPlanStepOut.cpp | 47 |
12 files changed, 247 insertions, 33 deletions
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); + } + } + } +} |

