Added support for stepping out of a frame. If you have 10 stack frames, and you
select frame #3, you can then do a step out and be able to go directly to the
frame above frame #3!
Added StepOverUntil and StepOutOfFrame to the SBThread API to allow more powerful
stepping.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@123970 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp
index 67ca2ff..2760e65 100644
--- a/source/API/SBThread.cpp
+++ b/source/API/SBThread.cpp
@@ -492,8 +492,53 @@
bool abort_other_plans = true;
bool stop_other_threads = true;
- m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans, NULL, false, stop_other_threads, eVoteYes, eVoteNoOpinion);
+ m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans,
+ NULL,
+ false,
+ stop_other_threads,
+ eVoteYes,
+ eVoteNoOpinion,
+ 0);
+
+ Process &process = m_opaque_sp->GetProcess();
+ process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
+ Error error (process.Resume());
+ if (error.Success())
+ {
+ // If we are doing synchronous mode, then wait for the
+ // process to stop yet again!
+ if (process.GetTarget().GetDebugger().GetAsyncExecution () == false)
+ process.WaitForProcessToStop (NULL);
+ }
+ }
+}
+void
+SBThread::StepOutOfFrame (lldb::SBFrame &sb_frame)
+{
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+
+ if (log)
+ {
+ SBStream frame_desc_strm;
+ sb_frame.GetDescription (frame_desc_strm);
+ log->Printf ("SBThread(%p)::StepOutOfFrame (frame = SBFrame(%p): %s)", m_opaque_sp.get(), sb_frame.get(), frame_desc_strm.GetData());
+ }
+
+ if (m_opaque_sp)
+ {
+ Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex());
+ bool abort_other_plans = true;
+ bool stop_other_threads = true;
+
+ m_opaque_sp->QueueThreadPlanForStepOut (abort_other_plans,
+ NULL,
+ false,
+ stop_other_threads,
+ eVoteYes,
+ eVoteNoOpinion,
+ sb_frame->GetFrameIndex());
+
Process &process = m_opaque_sp->GetProcess();
process.GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
Error error (process.Resume());
@@ -559,9 +604,141 @@
process.WaitForProcessToStop (NULL);
}
}
-
}
+SBError
+SBThread::StepOverUntil (lldb::SBFrame &sb_frame,
+ lldb::SBFileSpec &sb_file_spec,
+ uint32_t line)
+{
+ SBError sb_error;
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
+ char path[PATH_MAX];
+
+ if (log)
+ {
+ SBStream frame_desc_strm;
+ sb_frame.GetDescription (frame_desc_strm);
+ sb_file_spec->GetPath (path, sizeof(path));
+ log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)",
+ m_opaque_sp.get(),
+ sb_frame.get(),
+ frame_desc_strm.GetData(),
+ path, line);
+ }
+
+ if (m_opaque_sp)
+ {
+ Mutex::Locker api_locker (m_opaque_sp->GetProcess().GetTarget().GetAPIMutex());
+
+ if (line == 0)
+ {
+ sb_error.SetErrorString("invalid line argument");
+ return sb_error;
+ }
+
+ StackFrameSP frame_sp;
+ if (sb_frame.IsValid())
+ frame_sp = sb_frame.get_sp();
+ else
+ {
+ frame_sp = m_opaque_sp->GetSelectedFrame ();
+ if (!frame_sp)
+ frame_sp = m_opaque_sp->GetStackFrameAtIndex (0);
+ }
+
+ SymbolContext frame_sc;
+ if (!frame_sp)
+ {
+ sb_error.SetErrorString("no valid frames in thread to step");
+ return sb_error;
+ }
+
+ // If we have a frame, get its line
+ frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit |
+ eSymbolContextFunction |
+ eSymbolContextLineEntry |
+ eSymbolContextSymbol );
+
+ if (frame_sc.comp_unit == NULL)
+ {
+ sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex());
+ return sb_error;
+ }
+
+ FileSpec step_file_spec;
+ if (sb_file_spec.IsValid())
+ {
+ // The file spec passed in was valid, so use it
+ step_file_spec = sb_file_spec.ref();
+ }
+ else
+ {
+ if (frame_sc.line_entry.IsValid())
+ step_file_spec = frame_sc.line_entry.file;
+ else
+ {
+ sb_error.SetErrorString("invalid file argument or no file for frame");
+ return sb_error;
+ }
+ }
+
+ std::vector<addr_t> step_over_until_addrs;
+ const bool abort_other_plans = true;
+ const bool stop_other_threads = true;
+ const bool check_inlines = true;
+ const bool exact = false;
+
+ SymbolContextList sc_list;
+ const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec, line, check_inlines, exact, eSymbolContextLineEntry, sc_list);
+ if (num_matches > 0)
+ {
+ SymbolContext sc;
+ for (uint32_t i=0; i<num_matches; ++i)
+ {
+ if (sc_list.GetContextAtIndex(i, sc))
+ {
+ addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(&m_opaque_sp->GetProcess().GetTarget());
+ if (step_addr != LLDB_INVALID_ADDRESS)
+ {
+ step_over_until_addrs.push_back(step_addr);
+ }
+ }
+ }
+ }
+
+ if (step_over_until_addrs.empty())
+ {
+ step_file_spec.GetPath (path, sizeof(path));
+ sb_error.SetErrorStringWithFormat("No line entries for %s:u", path, line);
+ }
+ else
+ {
+ m_opaque_sp->QueueThreadPlanForStepUntil (abort_other_plans,
+ &step_over_until_addrs[0],
+ step_over_until_addrs.size(),
+ stop_other_threads,
+ frame_sp->GetFrameIndex());
+
+ m_opaque_sp->GetProcess().GetThreadList().SetSelectedThreadByID (m_opaque_sp->GetID());
+ sb_error.ref() = m_opaque_sp->GetProcess().Resume();
+ if (sb_error->Success())
+ {
+ // If we are doing synchronous mode, then wait for the
+ // process to stop yet again!
+ if (m_opaque_sp->GetProcess().GetTarget().GetDebugger().GetAsyncExecution () == false)
+ m_opaque_sp->GetProcess().WaitForProcessToStop (NULL);
+ }
+ }
+ }
+ else
+ {
+ sb_error.SetErrorString("this SBThread object is invalid");
+ }
+ return sb_error;
+}
+
+
bool
SBThread::Suspend()
{
@@ -606,10 +783,10 @@
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
if (log)
{
- SBStream sstr;
- process.GetDescription (sstr);
+ SBStream frame_desc_strm;
+ process.GetDescription (frame_desc_strm);
log->Printf ("SBThread(%p)::GetProcess () => SBProcess(%p): %s", m_opaque_sp.get(),
- process.get(), sstr.GetData());
+ process.get(), frame_desc_strm.GetData());
}
return process;
@@ -647,10 +824,10 @@
if (log)
{
- SBStream sstr;
- sb_frame.GetDescription (sstr);
+ SBStream frame_desc_strm;
+ sb_frame.GetDescription (frame_desc_strm);
log->Printf ("SBThread(%p)::GetFrameAtIndex (idx=%d) => SBFrame(%p): %s",
- m_opaque_sp.get(), idx, sb_frame.get(), sstr.GetData());
+ m_opaque_sp.get(), idx, sb_frame.get(), frame_desc_strm.GetData());
}
return sb_frame;
@@ -670,10 +847,10 @@
if (log)
{
- SBStream sstr;
- sb_frame.GetDescription (sstr);
+ SBStream frame_desc_strm;
+ sb_frame.GetDescription (frame_desc_strm);
log->Printf ("SBThread(%p)::GetSelectedFrame () => SBFrame(%p): %s",
- m_opaque_sp.get(), sb_frame.get(), sstr.GetData());
+ m_opaque_sp.get(), sb_frame.get(), frame_desc_strm.GetData());
}
return sb_frame;
@@ -698,10 +875,10 @@
if (log)
{
- SBStream sstr;
- sb_frame.GetDescription (sstr);
+ SBStream frame_desc_strm;
+ sb_frame.GetDescription (frame_desc_strm);
log->Printf ("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
- m_opaque_sp.get(), idx, sb_frame.get(), sstr.GetData());
+ m_opaque_sp.get(), idx, sb_frame.get(), frame_desc_strm.GetData());
}
return sb_frame;
}