diff options
author | Jim Ingham <jingham@apple.com> | 2012-09-01 01:02:41 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2012-09-01 01:02:41 +0000 |
commit | 513c6bb88cb8e9174465ec987498b14d345ce3a0 (patch) | |
tree | 3b53690275d3301cff8c5cc2852354a58b830b34 | |
parent | 4c05410f8f7d312fd45d8f156015cc2c13f5c977 (diff) | |
download | bcm5719-llvm-513c6bb88cb8e9174465ec987498b14d345ce3a0.tar.gz bcm5719-llvm-513c6bb88cb8e9174465ec987498b14d345ce3a0.zip |
Initial check-in of "fancy" inlined stepping. Doesn't do anything useful unless you switch LLDB_FANCY_INLINED_STEPPING to true. With that
on, basic inlined stepping works, including step-over of inlined functions. But for some as yet mysterious reason i386 debugging gets an
assert and dies immediately. So for now its off.
llvm-svn: 163044
-rw-r--r-- | lldb/include/lldb/Target/StackFrame.h | 5 | ||||
-rw-r--r-- | lldb/include/lldb/Target/StackFrameList.h | 25 | ||||
-rw-r--r-- | lldb/include/lldb/Target/Thread.h | 13 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadList.h | 13 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanStepInRange.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/Target/ThreadPlanStepOverRange.h | 4 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp | 9 | ||||
-rw-r--r-- | lldb/source/Target/Process.cpp | 8 | ||||
-rw-r--r-- | lldb/source/Target/StackFrame.cpp | 10 | ||||
-rw-r--r-- | lldb/source/Target/StackFrameList.cpp | 174 | ||||
-rw-r--r-- | lldb/source/Target/Thread.cpp | 18 | ||||
-rw-r--r-- | lldb/source/Target/ThreadList.cpp | 13 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepInRange.cpp | 34 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepOverRange.cpp | 68 |
14 files changed, 364 insertions, 32 deletions
diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 84f0e5be182..96811c117ed 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -130,10 +130,7 @@ public: IsInlined (); uint32_t - GetFrameIndex () const - { - return m_frame_index; - } + GetFrameIndex () const; uint32_t GetConcreteFrameIndex () const diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h index aa7f738a19b..f19a9c07f01 100644 --- a/lldb/include/lldb/Target/StackFrameList.h +++ b/lldb/include/lldb/Target/StackFrameList.h @@ -55,7 +55,19 @@ public: // Mark a stack frame as the current frame using the frame index bool SetSelectedFrameByIndex (uint32_t idx); - + + uint32_t + GetVisibleStackFrameIndex(uint32_t idx) + { + if (m_current_inlined_depth < UINT32_MAX) + return idx - m_current_inlined_depth; + else + return idx; + } + + void + CalculateCurrentInlinedDepth (); + void SetDefaultFileAndLineToSelectedFrame(); @@ -104,6 +116,15 @@ protected: m_concrete_frames_fetched = UINT32_MAX; } + bool + DecrementCurrentInlinedDepth (); + + void + ResetCurrentInlinedDepth(); + + uint32_t + GetCurrentInlinedDepth (); + //------------------------------------------------------------------ // Classes that inherit from StackFrameList can see and modify these //------------------------------------------------------------------ @@ -117,6 +138,8 @@ protected: collection m_frames; uint32_t m_selected_frame_idx; uint32_t m_concrete_frames_fetched; + uint32_t m_current_inlined_depth; + lldb::addr_t m_current_inlined_pc; bool m_show_inlined_frames; private: diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index b369a6e77a4..92f9e28e902 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -271,6 +271,18 @@ public: virtual lldb::StackFrameSP GetFrameWithConcreteFrameIndex (uint32_t unwind_idx); + bool + DecrementCurrentInlinedDepth() + { + return GetStackFrameList()->DecrementCurrentInlinedDepth(); + } + + uint32_t + GetCurrentInlinedDepth() + { + return GetStackFrameList()->DecrementCurrentInlinedDepth(); + } + virtual lldb::StackFrameSP GetFrameWithStackID (const StackID &stack_id) { @@ -706,6 +718,7 @@ protected: friend class ThreadPlan; friend class ThreadList; friend class StackFrameList; + friend class StackFrame; // This is necessary to make sure thread assets get destroyed while the thread is still in good shape // to call virtual thread methods. This must be called by classes that derive from Thread in their destructor. diff --git a/lldb/include/lldb/Target/ThreadList.h b/lldb/include/lldb/Target/ThreadList.h index 5acc87360eb..609cb518c12 100644 --- a/lldb/include/lldb/Target/ThreadList.h +++ b/lldb/include/lldb/Target/ThreadList.h @@ -92,6 +92,19 @@ public: void RefreshStateAfterStop (); + //------------------------------------------------------------------ + /// The thread list asks tells all the threads it is about to resume. + /// If a thread can "resume" without having to resume the target, it + /// will return false for WillResume, and then the process will not be + /// restarted. + /// + /// @return + /// \b true instructs the process to resume normally, + /// \b false means start & stopped events will be generated, but + /// the process will not actually run. The thread must then return + /// the correct StopInfo when asked. + /// + //------------------------------------------------------------------ bool WillResume (); diff --git a/lldb/include/lldb/Target/ThreadPlanStepInRange.h b/lldb/include/lldb/Target/ThreadPlanStepInRange.h index 664cedeb1d0..09f8fee337d 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepInRange.h +++ b/lldb/include/lldb/Target/ThreadPlanStepInRange.h @@ -52,6 +52,8 @@ public: virtual bool PlanExplainsStop (); + virtual bool WillResume (lldb::StateType resume_state, bool current_plan); + protected: virtual void diff --git a/lldb/include/lldb/Target/ThreadPlanStepOverRange.h b/lldb/include/lldb/Target/ThreadPlanStepOverRange.h index 21ede83ae6d..7423856a896 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepOverRange.h +++ b/lldb/include/lldb/Target/ThreadPlanStepOverRange.h @@ -35,7 +35,8 @@ public: virtual void GetDescription (Stream *s, lldb::DescriptionLevel level); virtual bool ShouldStop (Event *event_ptr); virtual bool PlanExplainsStop (); - + virtual bool WillResume (lldb::StateType resume_state, bool current_plan); + protected: private: @@ -47,6 +48,7 @@ private: const SymbolContext &addr_context, lldb::RunMode stop_others, bool avoid_code_without_debug_info); + bool m_first_resume; DISALLOW_COPY_AND_ASSIGN (ThreadPlanStepOverRange); diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index 55cb222ce47..95e4a9962dd 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -83,11 +83,16 @@ ThreadGDBRemote::GetQueueName () bool ThreadGDBRemote::WillResume (StateType resume_state) { - ClearStackFrames(); // Call the Thread::WillResume first. If we stop at a signal, the stop info // class for signal will set the resume signal that we need below. The signal // stuff obeys the Process::UnixSignal defaults. - Thread::WillResume(resume_state); + // If the thread's WillResume returns false, that means that we aren't going to actually resume, + // in which case we should not do the rest of our "resume" work. + + if (!Thread::WillResume(resume_state)) + return false; + + ClearStackFrames(); int signo = GetResumeSignal(); lldb::LogSP log(lldb_private::GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD)); diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index b16a37de3d1..9cbefffc82a 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -2975,7 +2975,13 @@ Process::PrivateResume () } else { - error.SetErrorStringWithFormat("Process::WillResume() thread list returned false after WillResume"); + // Somebody wanted to run without running. So generate a continue & a stopped event, + // and let the world handle them. + if (log) + log->Printf ("Process::PrivateResume() asked to simulate a start & stop."); + + SetPrivateState(eStateRunning); + SetPrivateState(eStateStopped); } } else if (log) diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp index 614223d97ff..932d35bea26 100644 --- a/lldb/source/Target/StackFrame.cpp +++ b/lldb/source/Target/StackFrame.cpp @@ -197,6 +197,16 @@ StackFrame::GetStackID() return m_id; } +uint32_t +StackFrame::GetFrameIndex () const +{ + ThreadSP thread_sp = GetThread(); + if (thread_sp) + return thread_sp->GetStackFrameList()->GetVisibleStackFrameIndex(m_frame_index); + else + return m_frame_index; +} + void StackFrame::SetSymbolContextScope (SymbolContextScope *symbol_scope) { diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp index 6fd410dd676..bfdb1a2f98d 100644 --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -21,6 +21,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/StopInfo.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/Unwind.h" @@ -45,8 +46,15 @@ StackFrameList::StackFrameList m_frames (), m_selected_frame_idx (0), m_concrete_frames_fetched (0), + m_current_inlined_depth (UINT32_MAX), + m_current_inlined_pc (LLDB_INVALID_ADDRESS), m_show_inlined_frames (show_inline_frames) { + if (prev_frames_sp) + { + m_current_inlined_depth = prev_frames_sp->m_current_inlined_depth; + m_current_inlined_pc = prev_frames_sp->m_current_inlined_pc; + } } //---------------------------------------------------------------------- @@ -57,6 +65,140 @@ StackFrameList::~StackFrameList() } void +StackFrameList::CalculateCurrentInlinedDepth() +{ + uint32_t cur_inlined_depth = GetCurrentInlinedDepth(); + if (cur_inlined_depth == UINT32_MAX) + { + ResetCurrentInlinedDepth(); + } +} + +uint32_t +StackFrameList::GetCurrentInlinedDepth () +{ + if (m_show_inlined_frames) + { + lldb::addr_t cur_pc = m_thread.GetRegisterContext()->GetPC(); + if (cur_pc != m_current_inlined_pc) + { + m_current_inlined_pc = LLDB_INVALID_ADDRESS; + m_current_inlined_depth = UINT32_MAX; + } + return m_current_inlined_depth; + } + else + { + return UINT32_MAX; + } +} + +static const bool LLDB_FANCY_INLINED_STEPPING = false; + +void +StackFrameList::ResetCurrentInlinedDepth () +{ + if (LLDB_FANCY_INLINED_STEPPING && m_show_inlined_frames) + { + GetFramesUpTo(0); + if (!m_frames[0]->IsInlined()) + { + m_current_inlined_depth = UINT32_MAX; + m_current_inlined_pc = LLDB_INVALID_ADDRESS; + } + else + { + // We only need to do something special about inlined blocks when we + // are at the beginning of an inlined function: + // FIXME: We probably also have to do something special if the PC is at the END + // of an inlined function, which coincides with the end of either its containing + // function or another inlined function. + + lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC(); + Block *block_ptr = m_frames[0]->GetFrameBlock(); + if (block_ptr) + { + Address pc_as_address; + pc_as_address.SetLoadAddress(curr_pc, &(m_thread.GetProcess()->GetTarget())); + AddressRange containing_range; + if (block_ptr->GetRangeContainingAddress(pc_as_address, containing_range)) + { + if (pc_as_address == containing_range.GetBaseAddress()) + { + // If we got here because of a breakpoint hit, then set the inlined depth depending on where + // the breakpoint was set. + // If we got here because of a crash, then set the inlined depth to the deepest most block. + // Otherwise, we stopped here naturally as the result of a step, so set ourselves in the + // containing frame of the whole set of nested inlines, so the user can then "virtually" + // step into the frames one by one, or next over the whole mess. + // Note: We don't have to handle being somewhere in the middle of the stack here, since + // ResetCurrentInlinedDepth doesn't get called if there is a valid inlined depth set. + StopInfoSP stop_info_sp = m_thread.GetStopInfo(); + if (stop_info_sp) + { + switch (stop_info_sp->GetStopReason()) + { + case eStopReasonBreakpoint: + { + + } + break; + case eStopReasonWatchpoint: + case eStopReasonException: + case eStopReasonSignal: + // In all these cases we want to stop in the deepest most frame. + m_current_inlined_pc = curr_pc; + m_current_inlined_depth = 0; + break; + default: + { + // Otherwise, we should set ourselves at the container of the inlining, so that the + // user can descend into them. + // So first we check whether we have more than one inlined block sharing this PC: + int num_inlined_functions = 0; + + for (Block *container_ptr = block_ptr->GetInlinedParent(); + container_ptr != NULL; + container_ptr = container_ptr->GetInlinedParent()) + { + if (!container_ptr->GetRangeContainingAddress(pc_as_address, containing_range)) + break; + if (pc_as_address != containing_range.GetBaseAddress()) + break; + + num_inlined_functions++; + } + m_current_inlined_pc = curr_pc; + m_current_inlined_depth = num_inlined_functions + 1; + + } + break; + } + } + } + } + } + } + } +} + +bool +StackFrameList::DecrementCurrentInlinedDepth () +{ + if (m_show_inlined_frames) + { + uint32_t current_inlined_depth = GetCurrentInlinedDepth(); + if (current_inlined_depth != UINT32_MAX) + { + if (current_inlined_depth > 0) + m_current_inlined_depth--; + return true; + } + } + return false; +} + +void StackFrameList::GetFramesUpTo(uint32_t end_idx) { // We've already gotten more frames than asked for, or we've already finished unwinding, return. @@ -70,6 +212,22 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx) #if defined (DEBUG_STACK_FRAMES) StreamFile s(stdout, false); #endif + // If we are hiding some frames from the outside world, we need to add those onto the total count of + // frames to fetch. However, we don't need ot do that if end_idx is 0 since in that case we always + // get the first concrete frame and all the inlined frames below it... + + uint32_t inlined_depth = 0; + if (end_idx > 0) + { + inlined_depth = GetCurrentInlinedDepth(); + if (inlined_depth != UINT32_MAX) + { + if (end_idx > 0) + end_idx += inlined_depth; + } + else + inlined_depth = 0; + } StackFrameSP unwind_frame_sp; do @@ -98,7 +256,7 @@ StackFrameList::GetFramesUpTo(uint32_t end_idx) unwind_frame_sp.reset (new StackFrame (m_thread.shared_from_this(), m_frames.size(), - idx, + idx, m_thread.m_reg_context_sp, cfa, pc, @@ -246,7 +404,12 @@ StackFrameList::GetNumFrames (bool can_create) if (can_create) GetFramesUpTo (UINT32_MAX); - return m_frames.size(); + + uint32_t inlined_depth = GetCurrentInlinedDepth(); + if (inlined_depth == UINT32_MAX) + return m_frames.size(); + else + return m_frames.size() - inlined_depth; } void @@ -278,6 +441,10 @@ StackFrameList::GetFrameAtIndex (uint32_t idx) { StackFrameSP frame_sp; Mutex::Locker locker (m_mutex); + uint32_t inlined_depth = GetCurrentInlinedDepth(); + if (inlined_depth != UINT32_MAX) + idx += inlined_depth; + if (idx < m_frames.size()) frame_sp = m_frames[idx]; @@ -396,6 +563,9 @@ StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) if (pos->get() == frame) { m_selected_frame_idx = std::distance (begin, pos); + uint32_t inlined_depth = GetCurrentInlinedDepth(); + if (inlined_depth != UINT32_MAX) + m_selected_frame_idx -= inlined_depth; break; } } diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 7ff006c6bce..9de1691cd47 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -349,15 +349,22 @@ Thread::WillResume (StateType resume_state) // plans in case a plan needs to do any special business before it runs. ThreadPlan *plan_ptr = GetCurrentPlan(); - plan_ptr->WillResume(resume_state, true); + bool need_to_resume = plan_ptr->WillResume(resume_state, true); while ((plan_ptr = GetPreviousPlan(plan_ptr)) != NULL) { plan_ptr->WillResume (resume_state, false); } - m_actual_stop_info_sp.reset(); - return true; + // If the WillResume for the plan says we are faking a resume, then it will have set an appropriate stop info. + // In that case, don't reset it here. + + if (need_to_resume) + { + m_actual_stop_info_sp.reset(); + } + + return need_to_resume; } void @@ -409,7 +416,10 @@ Thread::ShouldStop (Event* event_ptr) GetRegisterContext()->GetPC()); return false; } - + + // Adjust the stack frame's current inlined depth if it is needed. + GetStackFrameList()->CalculateCurrentInlinedDepth(); + if (log) { log->Printf ("Thread::%s for tid = 0x%4.4llx, pc = 0x%16.16llx", diff --git a/lldb/source/Target/ThreadList.cpp b/lldb/source/Target/ThreadList.cpp index 9bd2caf4126..0420c49014b 100644 --- a/lldb/source/Target/ThreadList.cpp +++ b/lldb/source/Target/ThreadList.cpp @@ -362,7 +362,6 @@ ThreadList::WillResume () // Run through the threads and perform their momentary actions. // But we only do this for threads that are running, user suspended // threads stay where they are. - bool success = true; Mutex::Locker locker(m_threads_mutex); m_process->UpdateThreadListIfNeeded(); @@ -449,6 +448,8 @@ ThreadList::WillResume () } + bool need_to_resume = true; + if (immediate_thread_sp) { for (pos = m_threads.begin(); pos != end; ++pos) @@ -471,7 +472,8 @@ ThreadList::WillResume () run_state = thread_sp->GetCurrentPlan()->RunState(); else run_state = eStateSuspended; - thread_sp->WillResume(run_state); + if (!thread_sp->WillResume(run_state)) + need_to_resume = false; } } else @@ -497,13 +499,16 @@ ThreadList::WillResume () { ThreadSP thread_sp(*pos); if (thread_sp == thread_to_run) - thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState()); + { + if (!thread_sp->WillResume(thread_sp->GetCurrentPlan()->RunState())) + need_to_resume = false; + } else thread_sp->WillResume (eStateSuspended); } } - return success; + return need_to_resume; } void diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp index a5243495150..8d4ac37e518 100644 --- a/lldb/source/Target/ThreadPlanStepInRange.cpp +++ b/lldb/source/Target/ThreadPlanStepInRange.cpp @@ -256,12 +256,12 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, { bool should_step_out = false; StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get(); - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 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"); @@ -306,7 +306,6 @@ 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. - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); StopInfoSP stop_info_sp = GetPrivateStopReason(); if (stop_info_sp) { @@ -320,9 +319,12 @@ ThreadPlanStepInRange::PlanExplainsStop () 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); + { + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + if (log) + log->PutCString ("ThreadPlanStepInRange got asked if it explains the stop for some reason other than step."); + SetPlanComplete(false); + } break; default: break; @@ -330,3 +332,25 @@ ThreadPlanStepInRange::PlanExplainsStop () } return true; } + +bool +ThreadPlanStepInRange::WillResume (lldb::StateType resume_state, bool current_plan) +{ + if (resume_state == eStateStepping && current_plan) + { + // See if we are about to step over a virtual inlined call. + bool step_without_resume = m_thread.DecrementCurrentInlinedDepth(); + if (step_without_resume) + { + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + if (log) + log->Printf ("ThreadPlanStepInRange::WillResume: returning false, inline_depth: %d", + m_thread.GetCurrentInlinedDepth()); + SetStopInfo(StopInfo::CreateStopReasonToTrace(m_thread)); + } + return !step_without_resume; + } + else + return ThreadPlan::WillResume(resume_state, current_plan); + +} diff --git a/lldb/source/Target/ThreadPlanStepOverRange.cpp b/lldb/source/Target/ThreadPlanStepOverRange.cpp index 08d9e4c7210..5298762124a 100644 --- a/lldb/source/Target/ThreadPlanStepOverRange.cpp +++ b/lldb/source/Target/ThreadPlanStepOverRange.cpp @@ -17,6 +17,8 @@ #include "lldb/lldb-private-log.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/Function.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" @@ -40,7 +42,8 @@ ThreadPlanStepOverRange::ThreadPlanStepOverRange const SymbolContext &addr_context, lldb::RunMode stop_others ) : - ThreadPlanStepRange (ThreadPlan::eKindStepOverRange, "Step range stepping over", thread, range, addr_context, stop_others) + ThreadPlanStepRange (ThreadPlan::eKindStepOverRange, "Step range stepping over", thread, range, addr_context, stop_others), + m_first_resume(true) { } @@ -116,7 +119,7 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) // in so I left out the target check. And sometimes the module comes in as the .o file from the // inlined range, so I left that out too... - bool older_ctx_is_equivalent = false; + bool older_ctx_is_equivalent = true; if (m_addr_context.comp_unit) { if (m_addr_context.comp_unit == older_context.comp_unit) @@ -126,10 +129,6 @@ ThreadPlanStepOverRange::ShouldStop (Event *event_ptr) if (m_addr_context.block && m_addr_context.block == older_context.block) { older_ctx_is_equivalent = true; - if (m_addr_context.line_entry.IsValid() && LineEntry::Compare(m_addr_context.line_entry, older_context.line_entry) != 0) - { - older_ctx_is_equivalent = false; - } } } } @@ -213,6 +212,9 @@ ThreadPlanStepOverRange::PlanExplainsStop () switch (reason) { + case eStopReasonTrace: + return true; + break; case eStopReasonBreakpoint: if (NextRangeBreakpointExplainsStop(stop_info_sp)) return true; @@ -222,13 +224,63 @@ ThreadPlanStepOverRange::PlanExplainsStop () case eStopReasonWatchpoint: case eStopReasonSignal: case eStopReasonException: + default: 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; } + +bool +ThreadPlanStepOverRange::WillResume (lldb::StateType resume_state, bool current_plan) +{ + if (resume_state != eStateSuspended && m_first_resume) + { + m_first_resume = false; + if (resume_state == eStateStepping && current_plan) + { + // See if we are about to step over an inlined call in the middle of the inlined stack, if so figure + // out its extents and reset our range to step over that. + bool in_inlined_stack = m_thread.DecrementCurrentInlinedDepth(); + if (in_inlined_stack) + { + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + if (log) + log->Printf ("ThreadPlanStepInRange::WillResume: adjusting range to the frame at inlined depth %d.", + m_thread.GetCurrentInlinedDepth()); + StackFrameSP stack_sp = m_thread.GetStackFrameAtIndex(0); + if (stack_sp) + { + Block *frame_block = stack_sp->GetFrameBlock(); + lldb::addr_t curr_pc = m_thread.GetRegisterContext()->GetPC(); + AddressRange my_range; + if (frame_block->GetRangeContainingLoadAddress(curr_pc, m_thread.GetProcess()->GetTarget(), my_range)) + { + m_address_ranges.clear(); + m_address_ranges.push_back(my_range); + if (log) + { + StreamString s; + const InlineFunctionInfo *inline_info = frame_block->GetInlinedFunctionInfo(); + const char *name; + if (inline_info) + name = inline_info->GetName().AsCString(); + else + name = "<unknown-notinlined>"; + + s.Printf ("Stepping over inlined function \"%s\" in inlined stack: ", name); + DumpRanges(&s); + log->PutCString(s.GetData()); + } + } + + } + } + } + } + + return ThreadPlan::WillResume(resume_state, current_plan); +} |