diff options
Diffstat (limited to 'source/Target/ThreadPlanShouldStopHere.cpp')
-rw-r--r-- | source/Target/ThreadPlanShouldStopHere.cpp | 142 |
1 files changed, 118 insertions, 24 deletions
diff --git a/source/Target/ThreadPlanShouldStopHere.cpp b/source/Target/ThreadPlanShouldStopHere.cpp index 87662345a06d..e89f5d2bde1b 100644 --- a/source/Target/ThreadPlanShouldStopHere.cpp +++ b/source/Target/ThreadPlanShouldStopHere.cpp @@ -23,12 +23,23 @@ using namespace lldb_private; //---------------------------------------------------------------------- // ThreadPlanShouldStopHere constructor //---------------------------------------------------------------------- -ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, ThreadPlanShouldStopHereCallback callback, void *baton) : - m_callback (callback), - m_baton (baton), +ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner) : + m_callbacks (), + m_baton (NULL), m_owner (owner), m_flags (ThreadPlanShouldStopHere::eNone) { + m_callbacks.should_stop_here_callback = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback; + m_callbacks.step_from_here_callback = ThreadPlanShouldStopHere::DefaultStepFromHereCallback; +} + +ThreadPlanShouldStopHere::ThreadPlanShouldStopHere(ThreadPlan *owner, const ThreadPlanShouldStopHereCallbacks *callbacks, void *baton) : + m_callbacks (), + m_baton (), + m_owner (owner), + m_flags (ThreadPlanShouldStopHere::eNone) +{ + SetShouldStopHereCallbacks(callbacks, baton); } //---------------------------------------------------------------------- @@ -38,37 +49,120 @@ ThreadPlanShouldStopHere::~ThreadPlanShouldStopHere() { } -void -ThreadPlanShouldStopHere::SetShouldStopHereCallback (ThreadPlanShouldStopHereCallback callback, void *baton) +bool +ThreadPlanShouldStopHere::InvokeShouldStopHereCallback (FrameComparison operation) { - m_callback = callback; - m_baton = baton; -} - -ThreadPlanSP -ThreadPlanShouldStopHere::InvokeShouldStopHereCallback () -{ - if (m_callback) + bool should_stop_here = true; + if (m_callbacks.should_stop_here_callback) { - ThreadPlanSP return_plan_sp(m_callback (m_owner, m_flags, m_baton)); + should_stop_here = m_callbacks.should_stop_here_callback (m_owner, m_flags, operation, m_baton); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); if (log) { lldb::addr_t current_addr = m_owner->GetThread().GetRegisterContext()->GetPC(0); - if (return_plan_sp) - { - StreamString s; - return_plan_sp->GetDescription (&s, lldb::eDescriptionLevelFull); - log->Printf ("ShouldStopHere callback found a step out plan from 0x%" PRIx64 ": %s.", current_addr, s.GetData()); - } - else - { - log->Printf ("ShouldStopHere callback didn't find a step out plan from: 0x%" PRIx64 ".", current_addr); - } + log->Printf ("ShouldStopHere callback returned %u from 0x%" PRIx64 ".", should_stop_here, current_addr); } + } + + return should_stop_here; +} + +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; +} + +ThreadPlanSP +ThreadPlanShouldStopHere::DefaultStepFromHereCallback (ThreadPlan *current_plan, + Flags &flags, + FrameComparison operation, + void *baton) +{ + const bool stop_others = false; + const size_t frame_index = 0; + ThreadPlanSP return_plan_sp; + // If we are stepping through code at line number 0, then we need to step over this range. Otherwise + // we will step out. + StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); + if (!frame) return return_plan_sp; + SymbolContext sc; + sc = frame->GetSymbolContext (eSymbolContextLineEntry); + if (sc.line_entry.line == 0) + { + AddressRange range = sc.line_entry.range; + return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOverRange(false, + range, + sc, + eOnlyDuringStepping, + eLazyBoolNo); + } + + if (!return_plan_sp) + return_plan_sp = current_plan->GetThread().QueueThreadPlanForStepOutNoShouldStop (false, + NULL, + true, + stop_others, + eVoteNo, + eVoteNoOpinion, + frame_index); + return return_plan_sp; +} + +ThreadPlanSP +ThreadPlanShouldStopHere::QueueStepOutFromHerePlan(lldb_private::Flags &flags, lldb::FrameComparison operation) +{ + ThreadPlanSP return_plan_sp; + if (m_callbacks.step_from_here_callback) + { + return_plan_sp = m_callbacks.step_from_here_callback (m_owner, flags, operation, m_baton); } + return return_plan_sp; + +} + +lldb::ThreadPlanSP +ThreadPlanShouldStopHere::CheckShouldStopHereAndQueueStepOut (lldb::FrameComparison operation) +{ + if (!InvokeShouldStopHereCallback(operation)) + return QueueStepOutFromHerePlan(m_flags, operation); else return ThreadPlanSP(); } + |