From 9aad861805c48c4a05655368b361141a1064847c Mon Sep 17 00:00:00 2001 From: Alexander Polyakov Date: Wed, 20 Jun 2018 21:43:16 +0000 Subject: [PATCH] Improve SBThread's stepping API using SBError parameter. Summary: The new methods will allow to get error messages from stepping API. Reviewers: aprantl, clayborg, labath, jingham Reviewed By: aprantl, clayborg, jingham Subscribers: apolyakov, labath, jingham, clayborg, lemo, lldb-commits Differential Revision: https://reviews.llvm.org/D47991 git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@335180 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/lldb/API/SBThread.h | 16 ++- scripts/interface/SBThread.i | 34 ++++- source/API/SBThread.cpp | 243 +++++++++++++++++++++-------------- 3 files changed, 195 insertions(+), 98 deletions(-) diff --git a/include/lldb/API/SBThread.h b/include/lldb/API/SBThread.h index 7f1cf10cc4..afc05d2c61 100644 --- a/include/lldb/API/SBThread.h +++ b/include/lldb/API/SBThread.h @@ -93,6 +93,8 @@ class LLDB_API SBThread { void StepOver(lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); + void StepOver(lldb::RunMode stop_other_threads, SBError &error); + void StepInto(lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); void StepInto(const char *target_name, @@ -103,10 +105,16 @@ class LLDB_API SBThread { void StepOut(); - void StepOutOfFrame(lldb::SBFrame &frame); + void StepOut(SBError &error); + + void StepOutOfFrame(SBFrame &frame); + + void StepOutOfFrame(SBFrame &frame, SBError &error); void StepInstruction(bool step_over); + void StepInstruction(bool step_over, SBError &error); + SBError StepOverUntil(lldb::SBFrame &frame, lldb::SBFileSpec &file_spec, uint32_t line); @@ -119,6 +127,8 @@ class LLDB_API SBThread { void RunToAddress(lldb::addr_t addr); + void RunToAddress(lldb::addr_t addr, SBError &error); + SBError ReturnFromFrame(SBFrame &frame, SBValue &return_value); SBError UnwindInnermostExpression(); @@ -146,8 +156,12 @@ class LLDB_API SBThread { //-------------------------------------------------------------------------- bool Suspend(); + bool Suspend(SBError &error); + bool Resume(); + bool Resume(SBError &error); + bool IsSuspended(); bool IsStopped(); diff --git a/scripts/interface/SBThread.i b/scripts/interface/SBThread.i index 823296cd4c..60d77c783b 100644 --- a/scripts/interface/SBThread.i +++ b/scripts/interface/SBThread.i @@ -211,6 +211,11 @@ public: void StepOver (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); + %feature("autodoc", + "Do a source level single step over in the currently selected thread.") StepOver; + void + StepOver (lldb::RunMode stop_other_threads, SBError &error); + void StepInto (lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); @@ -218,7 +223,7 @@ public: StepInto (const char *target_name, lldb::RunMode stop_other_threads = lldb::eOnlyDuringStepping); %feature("autodoc", " - Step the current thread from the current source line to the line given by end_line, stopping if + Step the current thread from the current source line to the line given by end_line, stopping if the thread steps into the function given by target_name. If target_name is None, then stepping will stop in any of the places we would normally stop. ") StepInto; @@ -231,12 +236,28 @@ public: void StepOut (); + %feature("autodoc", + "Step out of the currently selected thread.") StepOut; + void + StepOut (SBError &error); + void - StepOutOfFrame (lldb::SBFrame &frame); + StepOutOfFrame (SBFrame &frame); + + %feature("autodoc", + "Step out of the specified frame.") StepOutOfFrame; + void + StepOutOfFrame (SBFrame &frame, SBError &error); void StepInstruction(bool step_over); + %feature("autodoc", + "Do an instruction level single step in the currently selected thread. + ") StepInstruction; + void + StepInstruction(bool step_over, SBError &error); + SBError StepOverUntil (lldb::SBFrame &frame, lldb::SBFileSpec &file_spec, @@ -254,6 +275,9 @@ public: void RunToAddress (lldb::addr_t addr); + void + RunToAddress (lldb::addr_t addr, SBError &error); + %feature("autodoc", " Force a return from the frame passed in (and any frames younger than it) without executing any more code in those frames. If return_value contains @@ -297,9 +321,15 @@ public: ") Suspend; bool Suspend(); + + bool + Suspend(SBError &error); bool Resume (); + + bool + Resume (SBError &error); bool IsSuspended(); diff --git a/source/API/SBThread.cpp b/source/API/SBThread.cpp index def3b3a93f..0d25b85f57 100644 --- a/source/API/SBThread.cpp +++ b/source/API/SBThread.cpp @@ -633,6 +633,11 @@ SBError SBThread::ResumeNewPlan(ExecutionContext &exe_ctx, } void SBThread::StepOver(lldb::RunMode stop_other_threads) { + SBError error; // Ignored + StepOver(stop_other_threads, error); +} + +void SBThread::StepOver(lldb::RunMode stop_other_threads, SBError &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); std::unique_lock lock; @@ -643,28 +648,29 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads) { static_cast(exe_ctx.GetThreadPtr()), Thread::RunModeAsCString(stop_other_threads)); - if (exe_ctx.HasThreadScope()) { - Thread *thread = exe_ctx.GetThreadPtr(); - bool abort_other_plans = false; - StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0)); - - ThreadPlanSP new_plan_sp; - if (frame_sp) { - if (frame_sp->HasDebugInformation()) { - const LazyBool avoid_no_debug = eLazyBoolCalculate; - SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); - new_plan_sp = thread->QueueThreadPlanForStepOverRange( - abort_other_plans, sc.line_entry, sc, stop_other_threads, - avoid_no_debug); - } else { - new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( - true, abort_other_plans, stop_other_threads); - } - } + if (!exe_ctx.HasThreadScope()) { + error.SetErrorString("this SBThread object is invalid"); + return; + } + + Thread *thread = exe_ctx.GetThreadPtr(); + bool abort_other_plans = false; + StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0)); - // This returns an error, we should use it! - ResumeNewPlan(exe_ctx, new_plan_sp.get()); + ThreadPlanSP new_plan_sp; + if (frame_sp) { + if (frame_sp->HasDebugInformation()) { + const LazyBool avoid_no_debug = eLazyBoolCalculate; + SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); + new_plan_sp = thread->QueueThreadPlanForStepOverRange( + abort_other_plans, sc.line_entry, sc, stop_other_threads, + avoid_no_debug); + } else { + new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( + true, abort_other_plans, stop_other_threads); + } } + error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); } void SBThread::StepInto(lldb::RunMode stop_other_threads) { @@ -673,7 +679,7 @@ void SBThread::StepInto(lldb::RunMode stop_other_threads) { void SBThread::StepInto(const char *target_name, lldb::RunMode stop_other_threads) { - SBError error; + SBError error; // Ignored StepInto(target_name, LLDB_INVALID_LINE_NUMBER, error, stop_other_threads); } @@ -691,41 +697,48 @@ void SBThread::StepInto(const char *target_name, uint32_t end_line, target_name ? target_name : "", Thread::RunModeAsCString(stop_other_threads)); - if (exe_ctx.HasThreadScope()) { - bool abort_other_plans = false; + if (!exe_ctx.HasThreadScope()) { + error.SetErrorString("this SBThread object is invalid"); + return; + } - Thread *thread = exe_ctx.GetThreadPtr(); - StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0)); - ThreadPlanSP new_plan_sp; + bool abort_other_plans = false; - if (frame_sp && frame_sp->HasDebugInformation()) { - SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); - AddressRange range; - if (end_line == LLDB_INVALID_LINE_NUMBER) - range = sc.line_entry.range; - else { - if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref())) - return; - } - - const LazyBool step_out_avoids_code_without_debug_info = - eLazyBoolCalculate; - const LazyBool step_in_avoids_code_without_debug_info = - eLazyBoolCalculate; - new_plan_sp = thread->QueueThreadPlanForStepInRange( - abort_other_plans, range, sc, target_name, stop_other_threads, - step_in_avoids_code_without_debug_info, - step_out_avoids_code_without_debug_info); - } else { - new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( - false, abort_other_plans, stop_other_threads); + Thread *thread = exe_ctx.GetThreadPtr(); + StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0)); + ThreadPlanSP new_plan_sp; + + if (frame_sp && frame_sp->HasDebugInformation()) { + SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything)); + AddressRange range; + if (end_line == LLDB_INVALID_LINE_NUMBER) + range = sc.line_entry.range; + else { + if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref())) + return; } - error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); + const LazyBool step_out_avoids_code_without_debug_info = + eLazyBoolCalculate; + const LazyBool step_in_avoids_code_without_debug_info = + eLazyBoolCalculate; + new_plan_sp = thread->QueueThreadPlanForStepInRange( + abort_other_plans, range, sc, target_name, stop_other_threads, + step_in_avoids_code_without_debug_info, + step_out_avoids_code_without_debug_info); + } else { + new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction( + false, abort_other_plans, stop_other_threads); } + error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); } void SBThread::StepOut() { + SBError error; // Ignored + StepOut(error); +} + +void SBThread::StepOut(SBError &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); std::unique_lock lock; @@ -735,23 +748,30 @@ void SBThread::StepOut() { log->Printf("SBThread(%p)::StepOut ()", static_cast(exe_ctx.GetThreadPtr())); - if (exe_ctx.HasThreadScope()) { - bool abort_other_plans = false; - bool stop_other_threads = false; + if (!exe_ctx.HasThreadScope()) { + error.SetErrorString("this SBThread object is invalid"); + return; + } - Thread *thread = exe_ctx.GetThreadPtr(); + bool abort_other_plans = false; + bool stop_other_threads = false; + + Thread *thread = exe_ctx.GetThreadPtr(); - const LazyBool avoid_no_debug = eLazyBoolCalculate; - ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut( - abort_other_plans, NULL, false, stop_other_threads, eVoteYes, - eVoteNoOpinion, 0, avoid_no_debug)); + const LazyBool avoid_no_debug = eLazyBoolCalculate; + ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut( + abort_other_plans, NULL, false, stop_other_threads, eVoteYes, + eVoteNoOpinion, 0, avoid_no_debug)); - // This returns an error, we should use it! - ResumeNewPlan(exe_ctx, new_plan_sp.get()); - } + error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); } -void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) { +void SBThread::StepOutOfFrame(SBFrame &sb_frame) { + SBError error; // Ignored + StepOutOfFrame(sb_frame, error); +} + +void SBThread::StepOutOfFrame(SBFrame &sb_frame, SBError &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); std::unique_lock lock; @@ -762,6 +782,7 @@ void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) { log->Printf( "SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.", static_cast(exe_ctx.GetThreadPtr())); + error.SetErrorString("passed invalid SBFrame object"); return; } @@ -774,27 +795,36 @@ void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) { static_cast(frame_sp.get()), frame_desc_strm.GetData()); } - if (exe_ctx.HasThreadScope()) { - bool abort_other_plans = false; - bool stop_other_threads = false; - Thread *thread = exe_ctx.GetThreadPtr(); - if (sb_frame.GetThread().GetThreadID() != thread->GetID()) { - log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another " - "thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.", - static_cast(exe_ctx.GetThreadPtr()), - sb_frame.GetThread().GetThreadID(), thread->GetID()); - } - - ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut( - abort_other_plans, NULL, false, stop_other_threads, eVoteYes, - eVoteNoOpinion, frame_sp->GetFrameIndex())); + if (!exe_ctx.HasThreadScope()) { + error.SetErrorString("this SBThread object is invalid"); + return; + } - // This returns an error, we should use it! - ResumeNewPlan(exe_ctx, new_plan_sp.get()); + bool abort_other_plans = false; + bool stop_other_threads = false; + Thread *thread = exe_ctx.GetThreadPtr(); + if (sb_frame.GetThread().GetThreadID() != thread->GetID()) { + log->Printf("SBThread(%p)::StepOutOfFrame passed a frame from another " + "thread (0x%" PRIx64 " vrs. 0x%" PRIx64 ", returning.", + static_cast(exe_ctx.GetThreadPtr()), + sb_frame.GetThread().GetThreadID(), thread->GetID()); + error.SetErrorString("passed a frame from another thread"); + return; } + + ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepOut( + abort_other_plans, NULL, false, stop_other_threads, eVoteYes, + eVoteNoOpinion, frame_sp->GetFrameIndex())); + + error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); } void SBThread::StepInstruction(bool step_over) { + SBError error; // Ignored + StepInstruction(step_over, error); +} + +void SBThread::StepInstruction(bool step_over, SBError &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); std::unique_lock lock; @@ -804,17 +834,24 @@ void SBThread::StepInstruction(bool step_over) { log->Printf("SBThread(%p)::StepInstruction (step_over=%i)", static_cast(exe_ctx.GetThreadPtr()), step_over); - if (exe_ctx.HasThreadScope()) { - Thread *thread = exe_ctx.GetThreadPtr(); - ThreadPlanSP new_plan_sp( - thread->QueueThreadPlanForStepSingleInstruction(step_over, true, true)); - - // This returns an error, we should use it! - ResumeNewPlan(exe_ctx, new_plan_sp.get()); + if (!exe_ctx.HasThreadScope()) { + error.SetErrorString("this SBThread object is invalid"); + return; } + + Thread *thread = exe_ctx.GetThreadPtr(); + ThreadPlanSP new_plan_sp( + thread->QueueThreadPlanForStepSingleInstruction(step_over, true, true)); + + error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); } void SBThread::RunToAddress(lldb::addr_t addr) { + SBError error; // Ignored + RunToAddress(addr, error); +} + +void SBThread::RunToAddress(lldb::addr_t addr, SBError &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); std::unique_lock lock; @@ -824,20 +861,22 @@ void SBThread::RunToAddress(lldb::addr_t addr) { log->Printf("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")", static_cast(exe_ctx.GetThreadPtr()), addr); - if (exe_ctx.HasThreadScope()) { - bool abort_other_plans = false; - bool stop_other_threads = true; + if (!exe_ctx.HasThreadScope()) { + error.SetErrorString("this SBThread object is invalid"); + return; + } - Address target_addr(addr); + bool abort_other_plans = false; + bool stop_other_threads = true; - Thread *thread = exe_ctx.GetThreadPtr(); + Address target_addr(addr); + + Thread *thread = exe_ctx.GetThreadPtr(); - ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress( - abort_other_plans, target_addr, stop_other_threads)); + ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress( + abort_other_plans, target_addr, stop_other_threads)); - // This returns an error, we should use it! - ResumeNewPlan(exe_ctx, new_plan_sp.get()); - } + error = ResumeNewPlan(exe_ctx, new_plan_sp.get()); } SBError SBThread::StepOverUntil(lldb::SBFrame &sb_frame, @@ -1082,6 +1121,11 @@ SBError SBThread::UnwindInnermostExpression() { } bool SBThread::Suspend() { + SBError error; // Ignored + return Suspend(error); +} + +bool SBThread::Suspend(SBError &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); std::unique_lock lock; ExecutionContext exe_ctx(m_opaque_sp.get(), lock); @@ -1093,11 +1137,13 @@ bool SBThread::Suspend() { exe_ctx.GetThreadPtr()->SetResumeState(eStateSuspended); result = true; } else { + error.SetErrorString("process is running"); if (log) log->Printf("SBThread(%p)::Suspend() => error: process is running", static_cast(exe_ctx.GetThreadPtr())); } - } + } else + error.SetErrorString("this SBThread object is invalid"); if (log) log->Printf("SBThread(%p)::Suspend() => %i", static_cast(exe_ctx.GetThreadPtr()), result); @@ -1105,6 +1151,11 @@ bool SBThread::Suspend() { } bool SBThread::Resume() { + SBError error; // Ignored + return Resume(error); +} + +bool SBThread::Resume(SBError &error) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API)); std::unique_lock lock; ExecutionContext exe_ctx(m_opaque_sp.get(), lock); @@ -1117,11 +1168,13 @@ bool SBThread::Resume() { exe_ctx.GetThreadPtr()->SetResumeState(eStateRunning, override_suspend); result = true; } else { + error.SetErrorString("process is running"); if (log) log->Printf("SBThread(%p)::Resume() => error: process is running", static_cast(exe_ctx.GetThreadPtr())); } - } + } else + error.SetErrorString("this SBThread object is invalid"); if (log) log->Printf("SBThread(%p)::Resume() => %i", static_cast(exe_ctx.GetThreadPtr()), result);