diff options
author | Jim Ingham <jingham@apple.com> | 2011-05-17 01:10:11 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2011-05-17 01:10:11 +0000 |
commit | 160f78c5846c8fe774a1ccfc044d263b7b30ad9c (patch) | |
tree | 332b9c5e803a03b373d8609960a5f32b35f48671 | |
parent | ceee5e813364a34db3ad99926fd05dce69e4bb44 (diff) | |
download | llvm-160f78c5846c8fe774a1ccfc044d263b7b30ad9c.zip llvm-160f78c5846c8fe774a1ccfc044d263b7b30ad9c.tar.gz llvm-160f78c5846c8fe774a1ccfc044d263b7b30ad9c.tar.bz2 |
Fix the error message when an expression evaluation is interrupted by a crash/breakpoint hit to
give the reason for the interrupt. Also make sure it we don't want to unwind from the evaluation
we print something if it is interrupted.
llvm-svn: 131448
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlan.h | 12 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanCallFunction.h | 14 | ||||
-rw-r--r-- | lldb/source/Expression/ClangUserExpression.cpp | 19 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 41 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanCallFunction.cpp | 8 |
5 files changed, 82 insertions, 12 deletions
diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h index b6e4ca6..d848e54 100644 --- a/lldb/include/lldb/Target/ThreadPlan.h +++ b/lldb/include/lldb/Target/ThreadPlan.h @@ -377,6 +377,16 @@ public: m_tracer_sp->Log(); } + // Some thread plans hide away the actual stop info which caused any particular stop. For + // instance the ThreadPlanCallFunction restores the original stop reason so that stopping and + // calling a few functions won't lose the history of the run. + // This call can be implemented to get you back to the real stop info. + virtual lldb::StopInfoSP + GetRealStopInfo () + { + return m_thread.GetStopInfo (); + } + protected: //------------------------------------------------------------------ // Classes that inherit from ThreadPlan can see and modify these @@ -395,7 +405,7 @@ protected: lldb::StopInfoSP GetPrivateStopReason() { - return m_thread.GetPrivateStopReason(); + return m_thread.GetPrivateStopReason (); } void diff --git a/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/lldb/include/lldb/Target/ThreadPlanCallFunction.h index 3f2ac4a..76e0923 100644 --- a/lldb/include/lldb/Target/ThreadPlanCallFunction.h +++ b/lldb/include/lldb/Target/ThreadPlanCallFunction.h @@ -117,6 +117,16 @@ public: // thread state gets restored if the plan gets discarded. virtual void WillPop (); + + // If the thread plan stops mid-course, this will be the stop reason that interrupted us. + // Once DoTakedown is called, this will be the real stop reason at the end of the function call. + // This is needed because we want the CallFunction thread plans not to show up as the stop reason. + // But if something bad goes wrong, it is nice to be able to tell the user what really happened. + virtual lldb::StopInfoSP + GetRealStopInfo() + { + return m_real_stop_info_sp; + } protected: void ReportRegisterState (const char *message); @@ -145,6 +155,10 @@ private: LanguageRuntime *m_cxx_language_runtime; LanguageRuntime *m_objc_language_runtime; Thread::ThreadStateCheckpoint m_stored_thread_state; + lldb::StopInfoSP m_real_stop_info_sp; // In general we want to hide call function + // thread plans, but for reporting purposes, + // it's nice to know the real stop reason. + // This gets set in DoTakedown. lldb::ValueSP m_return_value_sp; // If this contains a valid pointer, use the ABI to extract values when complete bool m_takedown_done; // We want to ensure we only do the takedown once. This ensures that. diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index 6eafd7b..563c28a 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -504,7 +504,7 @@ ClangUserExpression::Execute (Stream &error_stream, lldb::addr_t function_stack_pointer = static_cast<ThreadPlanCallFunction *>(call_plan_sp.get())->GetFunctionStackPointer(); - call_plan_sp->SetPrivate(true); + // call_plan_sp->SetPrivate(true); uint32_t single_thread_timeout_usec = 500000; @@ -524,10 +524,23 @@ ClangUserExpression::Execute (Stream &error_stream, if (execution_result == eExecutionInterrupted) { + const char *error_desc = NULL; + + if (call_plan_sp) + { + lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); + if (real_stop_info_sp) + error_desc = real_stop_info_sp->GetDescription(); + } + if (error_desc) + error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc); + else + error_stream.Printf ("Execution was interrupted.", error_desc); + if (discard_on_error) - error_stream.Printf ("Expression execution was interrupted. The process has been returned to the state before execution."); + error_stream.Printf ("\nThe process has been returned to the state before execution."); else - error_stream.Printf ("Expression execution was interrupted. The process has been left at the point where it was interrupted."); + error_stream.Printf ("\nThe process has been left at the point where it was interrupted."); return execution_result; } diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index f185d57..88b813c 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -3498,11 +3498,40 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, switch (stop_state) { case lldb::eStateStopped: - // Yay, we're done. - if (log) - log->Printf ("Execution completed successfully."); - return_value = eExecutionCompleted; - break; + { + // Yay, we're done. Now make sure that our thread plan actually completed. + ThreadSP thread_sp = exe_ctx.process->GetThreadList().FindThreadByIndexID (tid); + if (!thread_sp) + { + // Ooh, our thread has vanished. Unlikely that this was successful execution... + if (log) + log->Printf ("Execution completed but our thread has vanished."); + return_value = eExecutionInterrupted; + } + else + { + StopInfoSP stop_info_sp = thread_sp->GetStopInfo (); + StopReason stop_reason = stop_info_sp->GetStopReason(); + if (stop_reason == eStopReasonPlanComplete) + { + if (log) + log->Printf ("Execution completed successfully."); + // Now mark this plan as private so it doesn't get reported as the stop reason + // after this point. + if (thread_plan_sp) + thread_plan_sp->SetPrivate (true); + return_value = eExecutionCompleted; + } + else + { + if (log) + log->Printf ("Thread plan didn't successfully complete."); + + return_value = eExecutionInterrupted; + } + } + } + break; case lldb::eStateCrashed: if (log) log->Printf ("Execution crashed."); @@ -3515,6 +3544,8 @@ Process::RunThreadPlan (ExecutionContext &exe_ctx, default: if (log) log->Printf("Execution stopped with unexpected state: %s.", StateAsCString(stop_state)); + + errors.Printf ("Execution stopped with unexpected state."); return_value = eExecutionInterrupted; break; } diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp index 371f3a4..7d798fc 100644 --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -282,6 +282,7 @@ ThreadPlanCallFunction::DoTakedown () if (log) log->Printf ("DoTakedown called for thread 0x%4.4x, m_valid: %d complete: %d.\n", m_thread.GetID(), m_valid, IsPlanComplete()); m_takedown_done = true; + m_real_stop_info_sp = GetPrivateStopReason(); m_thread.RestoreThreadStateFromCheckpoint(m_stored_thread_state); SetPlanComplete(); ClearBreakpoints(); @@ -327,6 +328,8 @@ ThreadPlanCallFunction::ValidatePlan (Stream *error) bool ThreadPlanCallFunction::PlanExplainsStop () { + m_real_stop_info_sp = GetPrivateStopReason(); + // If our subplan knows why we stopped, even if it's done (which would forward the question to us) // we answer yes. if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop()) @@ -343,11 +346,10 @@ ThreadPlanCallFunction::PlanExplainsStop () // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on. // If it is not an internal breakpoint, consult OkayToDiscard. - StopInfoSP stop_info_sp = GetPrivateStopReason(); - if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) + if (m_real_stop_info_sp && m_real_stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { - uint64_t break_site_id = stop_info_sp->GetValue(); + uint64_t break_site_id = m_real_stop_info_sp->GetValue(); BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id); if (bp_site_sp) { |