Fix reporting of stop reasons when the StepOver & StepIn plans stop because of a crash or breakpoint. Added the ability for a plan to say it is done but doesn't want to be the reason for the stop.

llvm-svn: 155927
This commit is contained in:
Jim Ingham 2012-05-01 18:38:37 +00:00
parent 758e0cc94a
commit fbbfe6ecf0
9 changed files with 103 additions and 41 deletions

View File

@ -142,6 +142,16 @@ namespace lldb_private {
// all threads will be called, the stop event is placed on the Process's public broadcaster, and
// control returns to the upper layers of the debugger.
//
// Reporting the stop:
//
// When the process stops, the thread is given a StopReason, in the form of a StopInfo object. If there is a completed
// plan corresponding to the stop, then the "actual" stop reason will be suppressed, and instead a StopInfoThreadPlan
// object will be cons'ed up from the highest completed plan in the stack. However, if the plan doesn't want to be
// the stop reason, then it can call SetPlanComplete and pass in "false" for the "success" parameter. In that case,
// the real stop reason will be used instead. One exapmle of this is the "StepRangeStepIn" thread plan. If it stops
// because of a crash or breakpoint hit, it wants to unship itself, because it isn't so useful to have step in keep going
// after a breakpoint hit. But it can't be the reason for the stop or no-one would see that they had hit a breakpoint.
//
// Automatically Resuming:
//
// If ShouldStop for all threads returns "false", then the target process will resume. This then cycles back to
@ -396,7 +406,13 @@ public:
IsPlanComplete();
void
SetPlanComplete ();
SetPlanComplete (bool success = true);
bool
PlanSucceeded ()
{
return m_plan_succeeded;
}
virtual bool
IsBasePlan()
@ -489,6 +505,7 @@ private:
bool m_plan_private;
bool m_okay_to_discard;
bool m_is_master_plan;
bool m_plan_succeeded;
lldb::ThreadPlanTracerSP m_tracer_sp;

View File

@ -49,6 +49,9 @@ public:
static void
SetDefaultFlagValue (uint32_t new_value);
virtual bool
PlanExplainsStop ();
protected:
virtual void

View File

@ -35,6 +35,7 @@ public:
virtual void GetDescription (Stream *s, lldb::DescriptionLevel level);
virtual bool ShouldStop (Event *event_ptr);
virtual bool PlanExplainsStop ();
protected:

View File

@ -42,7 +42,6 @@ public:
virtual lldb::StateType GetPlanRunState ();
virtual bool WillStop ();
virtual bool MischiefManaged ();
virtual bool PlanExplainsStop ();
virtual void DidPush ();

View File

@ -97,7 +97,7 @@ lldb::StopInfoSP
Thread::GetStopInfo ()
{
ThreadPlanSP plan_sp (GetCompletedPlan());
if (plan_sp)
if (plan_sp && plan_sp->PlanSucceeded())
return StopInfo::CreateStopReasonWithPlan (plan_sp, GetReturnValueObject());
else
{

View File

@ -37,7 +37,8 @@ ThreadPlan::ThreadPlan(ThreadPlanKind kind, const char *name, Thread &thread, Vo
m_plan_complete (false),
m_plan_private (false),
m_okay_to_discard (false),
m_is_master_plan (false)
m_is_master_plan (false),
m_plan_succeeded(true)
{
SetID (GetNextID());
}
@ -57,10 +58,11 @@ ThreadPlan::IsPlanComplete ()
}
void
ThreadPlan::SetPlanComplete ()
ThreadPlan::SetPlanComplete (bool success)
{
Mutex::Locker locker(m_plan_complete_mutex);
m_plan_complete = true;
m_plan_succeeded = success;
}
bool

View File

@ -295,3 +295,41 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
return NULL;
}
bool
ThreadPlanStepInRange::PlanExplainsStop ()
{
// We always explain a stop. Either we've just done a single step, in which
// case we'll do our ordinary processing, or we stopped for some
// reason that isn't handled by our sub-plans, in which case we want to just stop right
// away.
// We also set ourselves complete when we stop for this sort of unintended reason, but mark
// success as false so we don't end up being the reason for the stop.
//
// The only variation is that if we are doing "step by running to next branch" in which case
// if we hit our branch breakpoint we don't set the plan to complete.
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
StopInfoSP stop_info_sp = GetPrivateStopReason();
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
switch (reason)
{
case eStopReasonBreakpoint:
if (NextRangeBreakpointExplainsStop(stop_info_sp))
return true;
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
SetPlanComplete(false);
break;
default:
break;
}
}
return true;
}

View File

@ -170,3 +170,41 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr)
else
return false;
}
bool
ThreadPlanStepOverRange::PlanExplainsStop ()
{
// For crashes, breakpoint hits, signals, etc, let the base plan (or some plan above us)
// handle the stop. That way the user can see the stop, step around, and then when they
// are done, continue and have their step complete. The exception is if we've hit our
// "run to next branch" breakpoint.
// Note, unlike the step in range plan, we don't mark ourselves complete if we hit an
// unexplained breakpoint/crash.
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
StopInfoSP stop_info_sp = GetPrivateStopReason();
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
switch (reason)
{
case eStopReasonBreakpoint:
if (NextRangeBreakpointExplainsStop(stop_info_sp))
return true;
else
return false;
break;
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
return false;
break;
default:
break;
}
}
return true;
}

View File

@ -349,42 +349,6 @@ ThreadPlanStepRange::NextRangeBreakpointExplainsStop (lldb::StopInfoSP stop_info
return bp_site_sp->GetNumberOfOwners() == 1;
}
bool
ThreadPlanStepRange::PlanExplainsStop ()
{
// We always explain a stop. Either we've just done a single step, in which
// case we'll do our ordinary processing, or we stopped for some
// reason that isn't handled by our sub-plans, in which case we want to just stop right
// away.
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
StopInfoSP stop_info_sp = GetPrivateStopReason();
if (stop_info_sp)
{
StopReason reason = stop_info_sp->GetStopReason();
switch (reason)
{
case eStopReasonBreakpoint:
if (NextRangeBreakpointExplainsStop(stop_info_sp))
return true;
else
return false;
break;
case eStopReasonWatchpoint:
case eStopReasonSignal:
case eStopReasonException:
if (log)
log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step.");
SetPlanComplete();
break;
default:
break;
}
}
return true;
}
bool
ThreadPlanStepRange::WillStop ()
{