diff options
author | Greg Clayton <gclayton@apple.com> | 2011-01-21 06:11:58 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2011-01-21 06:11:58 +0000 |
commit | 481cef25dcbcd81a942d037004c573716a796c71 (patch) | |
tree | b9dd6cec5215fff40e47fcda3525314e1f3b9aa5 /lldb/source/API/SBThread.cpp | |
parent | 47ff14b091ee66a4c5f159e7fb8714ca9a66d2f9 (diff) | |
download | bcm5719-llvm-481cef25dcbcd81a942d037004c573716a796c71.tar.gz bcm5719-llvm-481cef25dcbcd81a942d037004c573716a796c71.zip |
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.
llvm-svn: 123970
Diffstat (limited to 'lldb/source/API/SBThread.cpp')
-rw-r--r-- | lldb/source/API/SBThread.cpp | 203 |
1 files changed, 190 insertions, 13 deletions
diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp index 67ca2ff2345..2760e6585a7 100644 --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -492,8 +492,53 @@ SBThread::StepOut () 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 @@ SBThread::RunToAddress (lldb::addr_t addr) 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 @@ SBThread::GetProcess () 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 @@ SBThread::GetFrameAtIndex (uint32_t idx) 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 @@ SBThread::GetSelectedFrame () 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 @@ SBThread::SetSelectedFrame (uint32_t idx) 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; } |