aboutsummaryrefslogtreecommitdiff
path: root/source/Target/ThreadPlanStepInRange.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Target/ThreadPlanStepInRange.cpp')
-rw-r--r--source/Target/ThreadPlanStepInRange.cpp132
1 files changed, 80 insertions, 52 deletions
diff --git a/source/Target/ThreadPlanStepInRange.cpp b/source/Target/ThreadPlanStepInRange.cpp
index c4cb9aba1b3e..3e9abef65573 100644
--- a/source/Target/ThreadPlanStepInRange.cpp
+++ b/source/Target/ThreadPlanStepInRange.cpp
@@ -31,7 +31,7 @@
using namespace lldb;
using namespace lldb_private;
-uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eAvoidNoDebug;
+uint32_t ThreadPlanStepInRange::s_default_flag_values = ThreadPlanShouldStopHere::eStepInAvoidNoDebug;
//----------------------------------------------------------------------
// ThreadPlanStepInRange: Step through a stack range, either stepping over or into
@@ -43,14 +43,18 @@ ThreadPlanStepInRange::ThreadPlanStepInRange
Thread &thread,
const AddressRange &range,
const SymbolContext &addr_context,
- lldb::RunMode stop_others
+ lldb::RunMode stop_others,
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info
) :
ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
- ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
+ ThreadPlanShouldStopHere (this),
m_step_past_prologue (true),
m_virtual_step (false)
{
+ SetCallbacks();
SetFlagsToDefault ();
+ SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info);
}
ThreadPlanStepInRange::ThreadPlanStepInRange
@@ -59,15 +63,19 @@ ThreadPlanStepInRange::ThreadPlanStepInRange
const AddressRange &range,
const SymbolContext &addr_context,
const char *step_into_target,
- lldb::RunMode stop_others
+ lldb::RunMode stop_others,
+ LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info
) :
ThreadPlanStepRange (ThreadPlan::eKindStepInRange, "Step Range stepping in", thread, range, addr_context, stop_others),
- ThreadPlanShouldStopHere (this, ThreadPlanStepInRange::DefaultShouldStopHereCallback, NULL),
+ ThreadPlanShouldStopHere (this),
m_step_past_prologue (true),
m_virtual_step (false),
m_step_into_target (step_into_target)
{
+ SetCallbacks();
SetFlagsToDefault ();
+ SetupAvoidNoDebug(step_in_avoids_code_without_debug_info, step_out_avoids_code_without_debug_info);
}
ThreadPlanStepInRange::~ThreadPlanStepInRange ()
@@ -75,6 +83,48 @@ ThreadPlanStepInRange::~ThreadPlanStepInRange ()
}
void
+ThreadPlanStepInRange::SetupAvoidNoDebug(LazyBool step_in_avoids_code_without_debug_info,
+ LazyBool step_out_avoids_code_without_debug_info)
+{
+ bool avoid_nodebug = true;
+
+ switch (step_in_avoids_code_without_debug_info)
+ {
+ case eLazyBoolYes:
+ avoid_nodebug = true;
+ break;
+ case eLazyBoolNo:
+ avoid_nodebug = false;
+ break;
+ case eLazyBoolCalculate:
+ avoid_nodebug = m_thread.GetStepInAvoidsNoDebug();
+ break;
+ }
+ if (avoid_nodebug)
+ GetFlags().Set (ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
+ else
+ GetFlags().Clear (ThreadPlanShouldStopHere::eStepInAvoidNoDebug);
+
+ avoid_nodebug = true;
+ switch (step_out_avoids_code_without_debug_info)
+ {
+ case eLazyBoolYes:
+ avoid_nodebug = true;
+ break;
+ case eLazyBoolNo:
+ avoid_nodebug = false;
+ break;
+ case eLazyBoolCalculate:
+ avoid_nodebug = m_thread.GetStepOutAvoidsNoDebug();
+ break;
+ }
+ if (avoid_nodebug)
+ GetFlags().Set (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+ else
+ GetFlags().Clear (ThreadPlanShouldStopHere::eStepOutAvoidNoDebug);
+}
+
+void
ThreadPlanStepInRange::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
if (level == lldb::eDescriptionLevelBrief)
@@ -124,7 +174,8 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
{
// If we've just completed a virtual step, all we need to do is check for a ShouldStopHere plan, and otherwise
// we're done.
- m_sub_plan_sp = InvokeShouldStopHereCallback();
+ // FIXME - This can be both a step in and a step out. Probably should record which in the m_virtual_step.
+ m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(eFrameCompareYounger);
}
else
{
@@ -139,7 +190,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
FrameComparison frame_order = CompareCurrentFrameToStartFrame();
- if (frame_order == eFrameCompareOlder)
+ if (frame_order == eFrameCompareOlder || frame_order == eFrameCompareSameParent)
{
// If we're in an older frame then we should stop.
//
@@ -148,7 +199,12 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
// in a trampoline we think the frame is older because the trampoline confused the backtracer.
m_sub_plan_sp = m_thread.QueueThreadPlanForStepThrough (m_stack_id, false, stop_others);
if (!m_sub_plan_sp)
- return true;
+ {
+ // Otherwise check the ShouldStopHere for step out:
+ m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
+ if (log)
+ log->Printf ("ShouldStopHere says we should step out of this frame.");
+ }
else if (log)
{
log->Printf("Thought I stepped out, but in fact arrived at a trampoline.");
@@ -196,7 +252,7 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
// 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 (!m_sub_plan_sp && frame_order == eFrameCompareYounger)
- m_sub_plan_sp = InvokeShouldStopHereCallback();
+ m_sub_plan_sp = CheckShouldStopHereAndQueueStepOut(frame_order);
// 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.
@@ -251,12 +307,6 @@ ThreadPlanStepInRange::ShouldStop (Event *event_ptr)
}
}
-void
-ThreadPlanStepInRange::SetFlagsToDefault ()
-{
- GetFlags().Set(ThreadPlanStepInRange::s_default_flag_values);
-}
-
void
ThreadPlanStepInRange::SetAvoidRegexp(const char *name)
{
@@ -344,25 +394,19 @@ ThreadPlanStepInRange::FrameMatchesAvoidCriteria ()
return false;
}
-ThreadPlanSP
-ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, void *baton)
+bool
+ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan, Flags &flags, FrameComparison operation, void *baton)
{
- bool should_step_out = false;
+ bool should_stop_here = true;
StackFrame *frame = current_plan->GetThread().GetStackFrameAtIndex(0).get();
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (flags.Test(eAvoidNoDebug))
- {
- if (!frame->HasDebugInformation())
- {
- if (log)
- log->Printf ("Stepping out of frame with no debug info");
-
- should_step_out = true;
- }
- }
+ // First see if the ThreadPlanShouldStopHere default implementation thinks we should get out of here:
+ should_stop_here = ThreadPlanShouldStopHere::DefaultShouldStopHereCallback (current_plan, flags, operation, baton);
+ if (!should_stop_here)
+ return should_stop_here;
- if (current_plan->GetKind() == eKindStepInRange)
+ if (should_stop_here && current_plan->GetKind() == eKindStepInRange && operation == eFrameCompareYounger)
{
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
if (step_in_range_plan->m_step_into_target)
@@ -373,7 +417,7 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
// 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;
+ should_stop_here = true;
}
else
{
@@ -381,42 +425,26 @@ ThreadPlanStepInRange::DefaultShouldStopHereCallback (ThreadPlan *current_plan,
const char *function_name = sc.GetFunctionName().AsCString();
if (function_name == NULL)
- should_step_out = true;
+ should_stop_here = false;
else if (strstr (function_name, target_name) == NULL)
- should_step_out = true;
+ should_stop_here = false;
}
- if (log && should_step_out)
+ if (log && !should_stop_here)
log->Printf("Stepping out of frame %s which did not match step into target %s.",
sc.GetFunctionName().AsCString(),
step_in_range_plan->m_step_into_target.AsCString());
}
}
- if (!should_step_out)
+ if (should_stop_here)
{
ThreadPlanStepInRange *step_in_range_plan = static_cast<ThreadPlanStepInRange *> (current_plan);
// Don't log the should_step_out here, it's easier to do it in FrameMatchesAvoidCriteria.
- should_step_out = step_in_range_plan->FrameMatchesAvoidCriteria ();
+ should_stop_here = !step_in_range_plan->FrameMatchesAvoidCriteria ();
}
}
-
- 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 ThreadPlanSP();
+ return should_stop_here;
}
bool