diff options
author | Jim Ingham <jingham@apple.com> | 2012-09-07 01:11:44 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2012-09-07 01:11:44 +0000 |
commit | f02a2e96b89600d227d2b9abca5bbdfee22c74c1 (patch) | |
tree | ce98295abc61be11fa0e1d53c09979b29db9d5af /lldb/source/Target/ThreadPlanStepInRange.cpp | |
parent | 7da851a3e291c29686c696bd40edaad3d5b64d43 (diff) | |
download | bcm5719-llvm-f02a2e96b89600d227d2b9abca5bbdfee22c74c1.tar.gz bcm5719-llvm-f02a2e96b89600d227d2b9abca5bbdfee22c74c1.zip |
Ensure that the ShouldStopHere plans get called even when doing "virtual" steps.
llvm-svn: 163366
Diffstat (limited to 'lldb/source/Target/ThreadPlanStepInRange.cpp')
-rw-r--r-- | lldb/source/Target/ThreadPlanStepInRange.cpp | 207 |
1 files changed, 112 insertions, 95 deletions
diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp index 8d4ac37e518..58fee69ff31 100644 --- a/lldb/source/Target/ThreadPlanStepInRange.cpp +++ b/lldb/source/Target/ThreadPlanStepInRange.cpp @@ -46,7 +46,8 @@ ThreadPlanStepInRange::ThreadPlanStepInRange ) : ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others), ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL), - m_step_past_prologue (true) + m_step_past_prologue (true), + m_virtual_step (false) { SetFlagsToDefault (); } @@ -86,113 +87,122 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr) ThreadPlan* new_plan = NULL; - // Stepping through should be done stopping other threads in general, since we're setting a breakpoint and - // continuing... - - bool stop_others; - if (m_stop_others != lldb::eAllThreads) - stop_others = true; - else - stop_others = false; - - FrameComparison frame_order = CompareCurrentFrameToStartFrame(); - - if (frame_order == eFrameCompareOlder) + if (m_virtual_step) { - // If we're in an older frame then we should stop. - // - // A caveat to this is if we think the frame is older but we're actually in a trampoline. - // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are - // in a trampoline we think the frame is older because the trampoline confused the backtracer. - new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); - if (new_plan == NULL) - return true; - else if (log) - { - log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); - } - + // If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise + // we're done. + new_plan = InvokeShouldStopHereCallback(); } - else if (frame_order == eFrameCompareEqual && InSymbol()) + else { - // If we are not in a place we should step through, we're done. - // One tricky bit here is that some stubs don't push a frame, so we have to check - // both the case of a frame that is younger, or the same as this frame. - // However, if the frame is the same, and we are still in the symbol we started - // in, the we don't need to do this. This first check isn't strictly necessary, - // but it is more efficient. + // Stepping through should be done stopping other threads in general, since we're setting a breakpoint and + // continuing... - // If we're still in the range, keep going, either by running to the next branch breakpoint, or by - // stepping. - if (InRange()) - { - SetNextBranchBreakpoint(); - return false; - } - - SetPlanComplete(); - return true; - } - - // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: - ClearNextBranchBreakpoint(); - - // We may have set the plan up above in the FrameIsOlder section: - - if (new_plan == NULL) - new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); - - if (log) - { - if (new_plan != NULL) - log->Printf ("Found a step through plan: %s", new_plan->GetName()); + bool stop_others; + if (m_stop_others != lldb::eAllThreads) + stop_others = true; else - log->Printf ("No step through plan found."); - } - - // If not, give the "should_stop" callback a chance to push a plan to get us out of here. - // But only do that if we actually have stepped in. - if (!new_plan && frame_order == eFrameCompareYounger) - new_plan = InvokeShouldStopHereCallback(); - - // If we've stepped in and we are going to stop here, check to see if we were asked to - // run past the prologue, and if so do that. - - if (new_plan == NULL && frame_order == eFrameCompareYounger && m_step_past_prologue) - { - lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); - if (curr_frame) - { - size_t bytes_to_skip = 0; - lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); - Address func_start_address; - - SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); + stop_others = false; - if (sc.function) + FrameComparison frame_order = CompareCurrentFrameToStartFrame(); + + if (frame_order == eFrameCompareOlder) + { + // If we're in an older frame then we should stop. + // + // A caveat to this is if we think the frame is older but we're actually in a trampoline. + // I'm going to make the assumption that you wouldn't RETURN to a trampoline. So if we are + // in a trampoline we think the frame is older because the trampoline confused the backtracer. + new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); + if (new_plan == NULL) + return true; + else if (log) { - func_start_address = sc.function->GetAddressRange().GetBaseAddress(); - if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) - bytes_to_skip = sc.function->GetPrologueByteSize(); + log->Printf("Thought I stepped out, but in fact arrived at a trampoline."); } - else if (sc.symbol) + + } + else if (frame_order == eFrameCompareEqual && InSymbol()) + { + // If we are not in a place we should step through, we're done. + // One tricky bit here is that some stubs don't push a frame, so we have to check + // both the case of a frame that is younger, or the same as this frame. + // However, if the frame is the same, and we are still in the symbol we started + // in, the we don't need to do this. This first check isn't strictly necessary, + // but it is more efficient. + + // If we're still in the range, keep going, either by running to the next branch breakpoint, or by + // stepping. + if (InRange()) { - func_start_address = sc.symbol->GetAddress(); - if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) - bytes_to_skip = sc.symbol->GetPrologueByteSize(); + SetNextBranchBreakpoint(); + return false; } - - if (bytes_to_skip != 0) + + SetPlanComplete(); + return true; + } + + // If we get to this point, we're not going to use a previously set "next branch" breakpoint, so delete it: + ClearNextBranchBreakpoint(); + + // We may have set the plan up above in the FrameIsOlder section: + + if (new_plan == NULL) + new_plan = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others); + + if (log) + { + if (new_plan != NULL) + log->Printf ("Found a step through plan: %s", new_plan->GetName()); + else + log->Printf ("No step through plan found."); + } + + // If not, give the "should_stop" callback a chance to push a plan to get us out of here. + // But only do that if we actually have stepped in. + if (!new_plan && frame_order == eFrameCompareYounger) + new_plan = InvokeShouldStopHereCallback(); + + // If we've stepped in and we are going to stop here, check to see if we were asked to + // run past the prologue, and if so do that. + + if (new_plan == NULL && frame_order == eFrameCompareYounger && m_step_past_prologue) + { + lldb::StackFrameSP curr_frame = m_thread.GetStackFrameAtIndex(0); + if (curr_frame) { - func_start_address.Slide (bytes_to_skip); - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); - if (log) - log->Printf ("Pushing past prologue "); - - new_plan = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); + size_t bytes_to_skip = 0; + lldb::addr_t curr_addr = m_thread.GetRegisterContext()->GetPC(); + Address func_start_address; + + SymbolContext sc = curr_frame->GetSymbolContext (eSymbolContextFunction | eSymbolContextSymbol); + + if (sc.function) + { + func_start_address = sc.function->GetAddressRange().GetBaseAddress(); + if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) + bytes_to_skip = sc.function->GetPrologueByteSize(); + } + else if (sc.symbol) + { + func_start_address = sc.symbol->GetAddress(); + if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) + bytes_to_skip = sc.symbol->GetPrologueByteSize(); + } + + if (bytes_to_skip != 0) + { + func_start_address.Slide (bytes_to_skip); + log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); + if (log) + log->Printf ("Pushing past prologue "); + + new_plan = m_thread.QueueThreadPlanForRunToAddress(false, func_start_address,true); + } } } - } + } if (new_plan == NULL) { @@ -306,6 +316,9 @@ ThreadPlanStepInRange::PlanExplainsStop () // 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. + if (m_virtual_step) + return true; + StopInfoSP stop_info_sp = GetPrivateStopReason(); if (stop_info_sp) { @@ -347,6 +360,10 @@ ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_pl log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d", m_thread.GetCurrentInlinedDepth()); SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); + + // FIXME: Maybe it would be better to create a InlineStep stop reason, but then + // the whole rest of the world would have to handle that stop reason. + m_virtual_step = true; } return !step_without_resume; } |