summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2012-09-01 01:02:41 +0000
committerJim Ingham <jingham@apple.com>2012-09-01 01:02:41 +0000
commit513c6bb88cb8e9174465ec987498b14d345ce3a0 (patch)
tree3b53690275d3301cff8c5cc2852354a58b830b34
parent4c05410f8f7d312fd45d8f156015cc2c13f5c977 (diff)
downloadbcm5719-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.h5
-rw-r--r--lldb/include/lldb/Target/StackFrameList.h25
-rw-r--r--lldb/include/lldb/Target/Thread.h13
-rw-r--r--lldb/include/lldb/Target/ThreadList.h13
-rw-r--r--lldb/include/lldb/Target/ThreadPlanStepInRange.h2
-rw-r--r--lldb/include/lldb/Target/ThreadPlanStepOverRange.h4
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp9
-rw-r--r--lldb/source/Target/Process.cpp8
-rw-r--r--lldb/source/Target/StackFrame.cpp10
-rw-r--r--lldb/source/Target/StackFrameList.cpp174
-rw-r--r--lldb/source/Target/Thread.cpp18
-rw-r--r--lldb/source/Target/ThreadList.cpp13
-rw-r--r--lldb/source/Target/ThreadPlanStepInRange.cpp34
-rw-r--r--lldb/source/Target/ThreadPlanStepOverRange.cpp68
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);
+}
OpenPOWER on IntegriCloud