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.
git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@163044 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Target/ThreadPlanStepOverRange.cpp b/source/Target/ThreadPlanStepOverRange.cpp
index 08d9e4c..5298762 100644
--- a/source/Target/ThreadPlanStepOverRange.cpp
+++ b/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 @@
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 @@
// 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 @@
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 @@
switch (reason)
{
+ case eStopReasonTrace:
+ return true;
+ break;
case eStopReasonBreakpoint:
if (NextRangeBreakpointExplainsStop(stop_info_sp))
return true;
@@ -222,13 +224,63 @@
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);
+}