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

llvm-svn: 335180
This commit is contained in:
Alexander Polyakov 2018-06-20 21:43:16 +00:00
parent 04ff58220f
commit 859f54b3f8
3 changed files with 201 additions and 104 deletions

View File

@ -93,6 +93,8 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
//--------------------------------------------------------------------------
bool Suspend();
bool Suspend(SBError &error);
bool Resume();
bool Resume(SBError &error);
bool IsSuspended();
bool IsStopped();

View File

@ -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
StepOutOfFrame (lldb::SBFrame &frame);
StepOut (SBError &error);
void
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();

View File

@ -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<std::recursive_mutex> lock;
@ -643,28 +648,29 @@ void SBThread::StepOver(lldb::RunMode stop_other_threads) {
static_cast<void *>(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);
}
}
// 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();
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);
}
}
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 : "<NULL>",
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;
}
Thread *thread = exe_ctx.GetThreadPtr();
StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
ThreadPlanSP new_plan_sp;
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);
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<std::recursive_mutex> lock;
@ -735,23 +748,30 @@ void SBThread::StepOut() {
log->Printf("SBThread(%p)::StepOut ()",
static_cast<void *>(exe_ctx.GetThreadPtr()));
if (exe_ctx.HasThreadScope()) {
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));
// 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;
}
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));
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<std::recursive_mutex> lock;
@ -762,6 +782,7 @@ void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) {
log->Printf(
"SBThread(%p)::StepOutOfFrame passed an invalid frame, returning.",
static_cast<void *>(exe_ctx.GetThreadPtr()));
error.SetErrorString("passed invalid SBFrame object");
return;
}
@ -774,27 +795,36 @@ void SBThread::StepOutOfFrame(lldb::SBFrame &sb_frame) {
static_cast<void *>(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<void *>(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()));
// 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;
}
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<void *>(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<std::recursive_mutex> lock;
@ -804,17 +834,24 @@ void SBThread::StepInstruction(bool step_over) {
log->Printf("SBThread(%p)::StepInstruction (step_over=%i)",
static_cast<void *>(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<std::recursive_mutex> lock;
@ -824,20 +861,22 @@ void SBThread::RunToAddress(lldb::addr_t addr) {
log->Printf("SBThread(%p)::RunToAddress (addr=0x%" PRIx64 ")",
static_cast<void *>(exe_ctx.GetThreadPtr()), addr);
if (exe_ctx.HasThreadScope()) {
bool abort_other_plans = false;
bool stop_other_threads = true;
Address target_addr(addr);
Thread *thread = exe_ctx.GetThreadPtr();
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());
if (!exe_ctx.HasThreadScope()) {
error.SetErrorString("this SBThread object is invalid");
return;
}
bool abort_other_plans = false;
bool stop_other_threads = true;
Address target_addr(addr);
Thread *thread = exe_ctx.GetThreadPtr();
ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForRunToAddress(
abort_other_plans, target_addr, stop_other_threads));
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<std::recursive_mutex> 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<void *>(exe_ctx.GetThreadPtr()));
}
}
} else
error.SetErrorString("this SBThread object is invalid");
if (log)
log->Printf("SBThread(%p)::Suspend() => %i",
static_cast<void *>(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<std::recursive_mutex> 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<void *>(exe_ctx.GetThreadPtr()));
}
}
} else
error.SetErrorString("this SBThread object is invalid");
if (log)
log->Printf("SBThread(%p)::Resume() => %i",
static_cast<void *>(exe_ctx.GetThreadPtr()), result);