bool
ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
                                                         Flags &flags,
                                                         FrameComparison operation,
                                                         void *baton)
{
    bool should_stop_here = true;
    StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
    if (!frame)
        return true;
    
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

    if ((operation == eFrameCompareOlder && flags.Test(eStepOutAvoidNoDebug))
        || (operation == eFrameCompareYounger && flags.Test(eStepInAvoidNoDebug))
        || (operation == eFrameCompareSameParent && flags.Test(eStepInAvoidNoDebug)))
    {
        if (!frame->HasDebugInformation())
        {
            if (log)
                log->Printf ("Stepping out of frame with no debug info");

            should_stop_here = false;
        }
    }
    
    // Always avoid code with line number 0.
    // FIXME: At present the ShouldStop and the StepFromHere calculate this independently.  If this ever
    // becomes expensive (this one isn't) we can try to have this set a state that the StepFromHere can use.
    if (frame)
    {
        SymbolContext sc;
        sc = frame->GetSymbolContext (eSymbolContextLineEntry);
        if (sc.line_entry.line == 0)
            should_stop_here = false;
    }
    
    return should_stop_here;
}
Beispiel #2
0
ThreadPlan *
ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
{
    bool should_step_out = false;
    StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();

    if (flags.Test(eAvoidNoDebug))
    {
        if (!frame->HasDebugInformation())
        {
            LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
            if (log)
                log->Printf ("Stepping out of frame with no debug info");

            should_step_out = true;
        }
    }
    
    if (current_plan->GetKind() == eKindStepInRange)
    {
        ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
        if (step_in_range_plan->m_step_into_target)
        {
            SymbolContext sc = frame->GetSymbolContext(eSymbolContextFunction|eSymbolContextBlock|eSymbolContextSymbol);
            if (sc.symbol != NULL)
            {
                // First try an exact match, since that's cheap with ConstStrings.  Then do a strstr compare.
                if (step_in_range_plan->m_step_into_target == sc.GetFunctionName())
                {
                    should_step_out = false;
                }
                else
                {
                    const char *target_name = step_in_range_plan->m_step_into_target.AsCString();
                    const char *function_name = sc.GetFunctionName().AsCString();
                    
                    if (function_name == NULL)
                        should_step_out = true;
                    else if (strstr (function_name, target_name) == NULL)
                        should_step_out = true;
                }
            }
        }
        
        if (!should_step_out)
        {
                ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
                should_step_out = step_in_range_plan->FrameMatchesAvoidRegexp ();
        }
    }
    
    
    if (should_step_out)
    {
        // FIXME: Make sure the ThreadPlanForStepOut does the right thing with inlined functions.
        // We really should have all plans take the tri-state for "stop others" so we can do the right
        // thing.  For now let's be safe and always run others when we are likely to run arbitrary code.
        const bool stop_others = false;
        return current_plan->GetThread().QueueThreadPlanForStepOut (false, 
                                                                    NULL, 
                                                                    true, 
                                                                    stop_others,
                                                                    eVoteNo, 
                                                                    eVoteNoOpinion,
                                                                    0); // Frame index
    }

    return NULL;
}