From 7a88ec9ac05c4f9e4cc03bd9e84af9e6da73c8b9 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Tue, 8 Jul 2014 19:28:57 +0000 Subject: [PATCH] Add the ability to provide a "count" option to the various "thread step-*" operations. Only step-inst and step-inst are currently supported, the rest just warn that they are not supported if you try to provide a count. llvm-svn: 212559 --- lldb/include/lldb/Target/ThreadPlan.h | 23 +++++ .../lldb/Target/ThreadPlanStepInstruction.h | 2 + lldb/source/Commands/CommandObjectThread.cpp | 19 +++++ .../Target/ThreadPlanStepInstruction.cpp | 84 ++++++++++++++++--- 4 files changed, 115 insertions(+), 13 deletions(-) diff --git a/lldb/include/lldb/Target/ThreadPlan.h b/lldb/include/lldb/Target/ThreadPlan.h index 85d11a099db8..1f20841906d3 100644 --- a/lldb/include/lldb/Target/ThreadPlan.h +++ b/lldb/include/lldb/Target/ThreadPlan.h @@ -539,6 +539,27 @@ public: return false; } + virtual bool + SetIterationCount (size_t count) + { + if (m_takes_iteration_count) + { + // Don't tell me to do something 0 times... + if (count == 0) + return false; + m_iteration_count = count; + } + return m_takes_iteration_count; + } + + virtual size_t + GetIterationCount () + { + if (!m_takes_iteration_count) + return 0; + else + return m_iteration_count; + } protected: //------------------------------------------------------------------ // Classes that inherit from ThreadPlan can see and modify these @@ -593,6 +614,8 @@ protected: Thread &m_thread; Vote m_stop_vote; Vote m_run_vote; + bool m_takes_iteration_count = false; + int32_t m_iteration_count = 1; private: //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Target/ThreadPlanStepInstruction.h b/lldb/include/lldb/Target/ThreadPlanStepInstruction.h index eb4a64bcbc84..86069ffd9eb5 100644 --- a/lldb/include/lldb/Target/ThreadPlanStepInstruction.h +++ b/lldb/include/lldb/Target/ThreadPlanStepInstruction.h @@ -32,6 +32,7 @@ public: virtual lldb::StateType GetPlanRunState (); virtual bool WillStop (); virtual bool MischiefManaged (); + virtual bool IsPlanStale (); protected: virtual bool DoPlanExplainsStop (Event *event_ptr); @@ -41,6 +42,7 @@ protected: bool stop_others, Vote stop_vote, Vote run_vote); + void SetUpState (); private: friend lldb::ThreadPlanSP diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 5dbdb164c221..36b5208bae19 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -371,6 +371,14 @@ public: } break; + case 'c': + { + m_step_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); + if (m_step_count == UINT32_MAX) + error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); + break; + } + break; case 'm': { OptionEnumValueElement *enum_values = g_option_table[option_idx].enum_values; @@ -408,6 +416,7 @@ public: m_run_mode = eOnlyDuringStepping; m_avoid_regexp.clear(); m_step_in_target.clear(); + m_step_count = 1; } const OptionDefinition* @@ -426,6 +435,7 @@ public: RunMode m_run_mode; std::string m_avoid_regexp; std::string m_step_in_target; + int32_t m_step_count; }; CommandObjectThreadStepWithTypeAndScope (CommandInterpreter &interpreter, @@ -603,6 +613,14 @@ protected: { new_plan_sp->SetIsMasterPlan (true); new_plan_sp->SetOkayToDiscard (false); + + if (m_options.m_step_count > 1) + { + if (new_plan_sp->SetIterationCount(m_options.m_step_count) != m_options.m_step_count) + { + result.AppendWarning ("step operation does not support iteration count."); + } + } process->GetThreadList().SetSelectedThreadByID (thread->GetID()); process->Resume (); @@ -664,6 +682,7 @@ CommandObjectThreadStepWithTypeAndScope::CommandOptions::g_option_table[] = { { LLDB_OPT_SET_1, false, "step-in-avoids-no-debug", 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "A boolean value that sets whether stepping into functions will step over functions with no debug information."}, { LLDB_OPT_SET_1, false, "step-out-avoids-no-debug", 'A', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "A boolean value, if true stepping out of functions will continue to step out till it hits a function with debug information."}, +{ LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 1, eArgTypeCount, "How many times to perform the stepping operation - currently only supported for step-inst and next-inst."}, { LLDB_OPT_SET_1, false, "run-mode", 'm', OptionParser::eRequiredArgument, g_tri_running_mode, 0, eArgTypeRunMode, "Determine how to run other threads while stepping the current thread."}, { LLDB_OPT_SET_1, false, "step-over-regexp",'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression, "A regular expression that defines function names to not to stop at when stepping in."}, { LLDB_OPT_SET_1, false, "step-in-target", 't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFunctionName, "The name of the directly called function step in should stop at when stepping into."}, diff --git a/lldb/source/Target/ThreadPlanStepInstruction.cpp b/lldb/source/Target/ThreadPlanStepInstruction.cpp index 8365d709ca8f..fabf63b1e9d6 100644 --- a/lldb/source/Target/ThreadPlanStepInstruction.cpp +++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp @@ -43,21 +43,28 @@ ThreadPlanStepInstruction::ThreadPlanStepInstruction m_stop_other_threads (stop_other_threads), m_step_over (step_over) { - m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0); - StackFrameSP m_start_frame_sp(m_thread.GetStackFrameAtIndex(0)); - m_stack_id = m_start_frame_sp->GetStackID(); - - m_start_has_symbol = m_start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL; - - StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1); - if (parent_frame_sp) - m_parent_frame_id = parent_frame_sp->GetStackID(); + m_takes_iteration_count = true; + SetUpState(); } ThreadPlanStepInstruction::~ThreadPlanStepInstruction () { } +void +ThreadPlanStepInstruction::SetUpState() +{ + m_instruction_addr = m_thread.GetRegisterContext()->GetPC(0); + StackFrameSP start_frame_sp(m_thread.GetStackFrameAtIndex(0)); + m_stack_id = start_frame_sp->GetStackID(); + + m_start_has_symbol = start_frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol != NULL; + + StackFrameSP parent_frame_sp = m_thread.GetStackFrameAtIndex(1); + if (parent_frame_sp) + m_parent_frame_id = parent_frame_sp->GetStackID(); +} + void ThreadPlanStepInstruction::GetDescription (Stream *s, lldb::DescriptionLevel level) { @@ -105,6 +112,37 @@ ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr) return false; } +bool +ThreadPlanStepInstruction::IsPlanStale () +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + StackID cur_frame_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); + if (cur_frame_id == m_stack_id) + { + if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) + return true; + else + return false; + } + else if (cur_frame_id < m_stack_id) + { + // If the current frame is younger than the start frame and we are stepping over, then we need to continue, + // but if we are doing just one step, we're done. + if (m_step_over) + return false; + else + return true; + } + else + { + if (log) + { + log->Printf ("ThreadPlanStepInstruction::IsPlanStale - Current frame is older than start frame, plan is stale."); + } + return true; + } +} + bool ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) { @@ -118,8 +156,18 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) { if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) { - SetPlanComplete(); - return true; + if (--m_iteration_count <= 0) + { + SetPlanComplete(); + return true; + } + else + { + // We are still stepping, reset the start pc, and in case we've stepped out, + // reset the current stack id. + SetUpState(); + return false; + } } else return false; @@ -182,8 +230,18 @@ ThreadPlanStepInstruction::ShouldStop (Event *event_ptr) { if (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr) { - SetPlanComplete(); - return true; + if (--m_iteration_count <= 0) + { + SetPlanComplete(); + return true; + } + else + { + // We are still stepping, reset the start pc, and in case we've stepped in or out, + // reset the current stack id. + SetUpState(); + return false; + } } else return false;