forked from OSchip/llvm-project
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
This commit is contained in:
parent
ceee5e8133
commit
160f78c584
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
if (discard_on_error)
|
||||
error_stream.Printf ("Expression execution was interrupted. The process has been returned to the state before execution.");
|
||||
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 ("Expression execution was interrupted. The process has been left at the point where it was interrupted.");
|
||||
error_stream.Printf ("Execution was interrupted.", error_desc);
|
||||
|
||||
if (discard_on_error)
|
||||
error_stream.Printf ("\nThe process has been returned to the state before execution.");
|
||||
else
|
||||
error_stream.Printf ("\nThe process has been left at the point where it was interrupted.");
|
||||
|
||||
return execution_result;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue