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; }
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; }