diff options
Diffstat (limited to 'lldb/source/Target/ThreadPlanStepUntil.cpp')
-rw-r--r-- | lldb/source/Target/ThreadPlanStepUntil.cpp | 596 |
1 files changed, 271 insertions, 325 deletions
diff --git a/lldb/source/Target/ThreadPlanStepUntil.cpp b/lldb/source/Target/ThreadPlanStepUntil.cpp index 2581fc7..a10e2f4 100644 --- a/lldb/source/Target/ThreadPlanStepUntil.cpp +++ b/lldb/source/Target/ThreadPlanStepUntil.cpp @@ -23,371 +23,317 @@ using namespace lldb; using namespace lldb_private; //---------------------------------------------------------------------- -// ThreadPlanStepUntil: Run until we reach a given line number or step out of the current frame +// ThreadPlanStepUntil: Run until we reach a given line number or step out of +// the current frame //---------------------------------------------------------------------- -ThreadPlanStepUntil::ThreadPlanStepUntil -( - Thread &thread, - lldb::addr_t *address_list, - size_t num_addresses, - bool stop_others, - uint32_t frame_idx -) : - ThreadPlan (ThreadPlan::eKindStepUntil, "Step until", thread, eVoteNoOpinion, eVoteNoOpinion), - m_step_from_insn (LLDB_INVALID_ADDRESS), - m_return_bp_id (LLDB_INVALID_BREAK_ID), - m_return_addr (LLDB_INVALID_ADDRESS), - m_stepped_out (false), - m_should_stop (false), - m_ran_analyze (false), - m_explains_stop (false), - m_until_points (), - m_stop_others (stop_others) -{ - // Stash away our "until" addresses: - TargetSP target_sp (m_thread.CalculateTarget()); - - StackFrameSP frame_sp (m_thread.GetStackFrameAtIndex (frame_idx)); - if (frame_sp) - { - m_step_from_insn = frame_sp->GetStackID().GetPC(); - lldb::user_id_t thread_id = m_thread.GetID(); - - // Find the return address and set a breakpoint there: - // FIXME - can we do this more securely if we know first_insn? - - StackFrameSP return_frame_sp (m_thread.GetStackFrameAtIndex(frame_idx + 1)); - if (return_frame_sp) - { - // TODO: add inline functionality - m_return_addr = return_frame_sp->GetStackID().GetPC(); - Breakpoint *return_bp = target_sp->CreateBreakpoint (m_return_addr, true, false).get(); - if (return_bp != nullptr) - { - return_bp->SetThreadID(thread_id); - m_return_bp_id = return_bp->GetID(); - return_bp->SetBreakpointKind ("until-return-backstop"); - } - } +ThreadPlanStepUntil::ThreadPlanStepUntil(Thread &thread, + lldb::addr_t *address_list, + size_t num_addresses, bool stop_others, + uint32_t frame_idx) + : ThreadPlan(ThreadPlan::eKindStepUntil, "Step until", thread, + eVoteNoOpinion, eVoteNoOpinion), + m_step_from_insn(LLDB_INVALID_ADDRESS), + m_return_bp_id(LLDB_INVALID_BREAK_ID), + m_return_addr(LLDB_INVALID_ADDRESS), m_stepped_out(false), + m_should_stop(false), m_ran_analyze(false), m_explains_stop(false), + m_until_points(), m_stop_others(stop_others) { + // Stash away our "until" addresses: + TargetSP target_sp(m_thread.CalculateTarget()); + + StackFrameSP frame_sp(m_thread.GetStackFrameAtIndex(frame_idx)); + if (frame_sp) { + m_step_from_insn = frame_sp->GetStackID().GetPC(); + lldb::user_id_t thread_id = m_thread.GetID(); + + // Find the return address and set a breakpoint there: + // FIXME - can we do this more securely if we know first_insn? + + StackFrameSP return_frame_sp(m_thread.GetStackFrameAtIndex(frame_idx + 1)); + if (return_frame_sp) { + // TODO: add inline functionality + m_return_addr = return_frame_sp->GetStackID().GetPC(); + Breakpoint *return_bp = + target_sp->CreateBreakpoint(m_return_addr, true, false).get(); + if (return_bp != nullptr) { + return_bp->SetThreadID(thread_id); + m_return_bp_id = return_bp->GetID(); + return_bp->SetBreakpointKind("until-return-backstop"); + } + } - m_stack_id = frame_sp->GetStackID(); - - // Now set breakpoints on all our return addresses: - for (size_t i = 0; i < num_addresses; i++) - { - Breakpoint *until_bp = target_sp->CreateBreakpoint (address_list[i], true, false).get(); - if (until_bp != nullptr) - { - until_bp->SetThreadID(thread_id); - m_until_points[address_list[i]] = until_bp->GetID(); - until_bp->SetBreakpointKind("until-target"); - } - else - { - m_until_points[address_list[i]] = LLDB_INVALID_BREAK_ID; - } - } + m_stack_id = frame_sp->GetStackID(); + + // Now set breakpoints on all our return addresses: + for (size_t i = 0; i < num_addresses; i++) { + Breakpoint *until_bp = + target_sp->CreateBreakpoint(address_list[i], true, false).get(); + if (until_bp != nullptr) { + until_bp->SetThreadID(thread_id); + m_until_points[address_list[i]] = until_bp->GetID(); + until_bp->SetBreakpointKind("until-target"); + } else { + m_until_points[address_list[i]] = LLDB_INVALID_BREAK_ID; + } } + } } -ThreadPlanStepUntil::~ThreadPlanStepUntil () -{ - Clear(); -} +ThreadPlanStepUntil::~ThreadPlanStepUntil() { Clear(); } -void -ThreadPlanStepUntil::Clear() -{ - TargetSP target_sp (m_thread.CalculateTarget()); - if (target_sp) - { - if (m_return_bp_id != LLDB_INVALID_BREAK_ID) - { - target_sp->RemoveBreakpointByID(m_return_bp_id); - m_return_bp_id = LLDB_INVALID_BREAK_ID; - } +void ThreadPlanStepUntil::Clear() { + TargetSP target_sp(m_thread.CalculateTarget()); + if (target_sp) { + if (m_return_bp_id != LLDB_INVALID_BREAK_ID) { + target_sp->RemoveBreakpointByID(m_return_bp_id); + m_return_bp_id = LLDB_INVALID_BREAK_ID; + } - until_collection::iterator pos, end = m_until_points.end(); - for (pos = m_until_points.begin(); pos != end; pos++) - { - target_sp->RemoveBreakpointByID((*pos).second); - } + until_collection::iterator pos, end = m_until_points.end(); + for (pos = m_until_points.begin(); pos != end; pos++) { + target_sp->RemoveBreakpointByID((*pos).second); } - m_until_points.clear(); + } + m_until_points.clear(); } -void -ThreadPlanStepUntil::GetDescription (Stream *s, lldb::DescriptionLevel level) -{ - if (level == lldb::eDescriptionLevelBrief) - { - s->Printf ("step until"); - if (m_stepped_out) - s->Printf (" - stepped out"); - } - else - { - if (m_until_points.size() == 1) - s->Printf ("Stepping from address 0x%" PRIx64 " until we reach 0x%" PRIx64 " using breakpoint %d", - (uint64_t)m_step_from_insn, - (uint64_t) (*m_until_points.begin()).first, - (*m_until_points.begin()).second); - else - { - until_collection::iterator pos, end = m_until_points.end(); - s->Printf ("Stepping from address 0x%" PRIx64 " until we reach one of:", - (uint64_t)m_step_from_insn); - for (pos = m_until_points.begin(); pos != end; pos++) - { - s->Printf ("\n\t0x%" PRIx64 " (bp: %d)", (uint64_t) (*pos).first, (*pos).second); - } - } - s->Printf(" stepped out address is 0x%" PRIx64 ".", (uint64_t) m_return_addr); +void ThreadPlanStepUntil::GetDescription(Stream *s, + lldb::DescriptionLevel level) { + if (level == lldb::eDescriptionLevelBrief) { + s->Printf("step until"); + if (m_stepped_out) + s->Printf(" - stepped out"); + } else { + if (m_until_points.size() == 1) + s->Printf("Stepping from address 0x%" PRIx64 " until we reach 0x%" PRIx64 + " using breakpoint %d", + (uint64_t)m_step_from_insn, + (uint64_t)(*m_until_points.begin()).first, + (*m_until_points.begin()).second); + else { + until_collection::iterator pos, end = m_until_points.end(); + s->Printf("Stepping from address 0x%" PRIx64 " until we reach one of:", + (uint64_t)m_step_from_insn); + for (pos = m_until_points.begin(); pos != end; pos++) { + s->Printf("\n\t0x%" PRIx64 " (bp: %d)", (uint64_t)(*pos).first, + (*pos).second); + } } + s->Printf(" stepped out address is 0x%" PRIx64 ".", + (uint64_t)m_return_addr); + } } -bool -ThreadPlanStepUntil::ValidatePlan (Stream *error) -{ - if (m_return_bp_id == LLDB_INVALID_BREAK_ID) +bool ThreadPlanStepUntil::ValidatePlan(Stream *error) { + if (m_return_bp_id == LLDB_INVALID_BREAK_ID) + return false; + else { + until_collection::iterator pos, end = m_until_points.end(); + for (pos = m_until_points.begin(); pos != end; pos++) { + if (!LLDB_BREAK_ID_IS_VALID((*pos).second)) return false; - else - { - until_collection::iterator pos, end = m_until_points.end(); - for (pos = m_until_points.begin(); pos != end; pos++) - { - if (!LLDB_BREAK_ID_IS_VALID ((*pos).second)) - return false; - } - return true; } + return true; + } } -void -ThreadPlanStepUntil::AnalyzeStop() -{ - if (m_ran_analyze) +void ThreadPlanStepUntil::AnalyzeStop() { + if (m_ran_analyze) + return; + + StopInfoSP stop_info_sp = GetPrivateStopInfo(); + m_should_stop = true; + m_explains_stop = false; + + if (stop_info_sp) { + StopReason reason = stop_info_sp->GetStopReason(); + + if (reason == eStopReasonBreakpoint) { + // If this is OUR breakpoint, we're fine, otherwise we don't know why this + // happened... + BreakpointSiteSP this_site = + m_thread.GetProcess()->GetBreakpointSiteList().FindByID( + stop_info_sp->GetValue()); + if (!this_site) { + m_explains_stop = false; return; - - StopInfoSP stop_info_sp = GetPrivateStopInfo (); - m_should_stop = true; - m_explains_stop = false; - - if (stop_info_sp) - { - StopReason reason = stop_info_sp->GetStopReason(); - - if (reason == eStopReasonBreakpoint) - { - // If this is OUR breakpoint, we're fine, otherwise we don't know why this happened... - BreakpointSiteSP this_site = m_thread.GetProcess()->GetBreakpointSiteList().FindByID (stop_info_sp->GetValue()); - if (!this_site) - { - m_explains_stop = false; - return; + } + + if (this_site->IsBreakpointAtThisSite(m_return_bp_id)) { + // If we are at our "step out" breakpoint, and the stack depth has + // shrunk, then + // this is indeed our stop. + // If the stack depth has grown, then we've hit our step out breakpoint + // recursively. + // If we are the only breakpoint at that location, then we do explain + // the stop, and + // we'll just continue. + // If there was another breakpoint here, then we don't explain the stop, + // but we won't + // mark ourselves Completed, because maybe that breakpoint will + // continue, and then + // we'll finish the "until". + bool done; + StackID cur_frame_zero_id; + + done = (m_stack_id < cur_frame_zero_id); + + if (done) { + m_stepped_out = true; + SetPlanComplete(); + } else + m_should_stop = false; + + if (this_site->GetNumberOfOwners() == 1) + m_explains_stop = true; + else + m_explains_stop = false; + return; + } else { + // Check if we've hit one of our "until" breakpoints. + until_collection::iterator pos, end = m_until_points.end(); + for (pos = m_until_points.begin(); pos != end; pos++) { + if (this_site->IsBreakpointAtThisSite((*pos).second)) { + // If we're at the right stack depth, then we're done. + + bool done; + StackID frame_zero_id = + m_thread.GetStackFrameAtIndex(0)->GetStackID(); + + if (frame_zero_id == m_stack_id) + done = true; + else if (frame_zero_id < m_stack_id) + done = false; + else { + StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1); + + // But if we can't even unwind one frame we should just get out of + // here & stop... + if (older_frame_sp) { + const SymbolContext &older_context = + older_frame_sp->GetSymbolContext(eSymbolContextEverything); + SymbolContext stack_context; + m_stack_id.GetSymbolContextScope()->CalculateSymbolContext( + &stack_context); + + done = (older_context == stack_context); + } else + done = false; } - if (this_site->IsBreakpointAtThisSite (m_return_bp_id)) - { - // If we are at our "step out" breakpoint, and the stack depth has shrunk, then - // this is indeed our stop. - // If the stack depth has grown, then we've hit our step out breakpoint recursively. - // If we are the only breakpoint at that location, then we do explain the stop, and - // we'll just continue. - // If there was another breakpoint here, then we don't explain the stop, but we won't - // mark ourselves Completed, because maybe that breakpoint will continue, and then - // we'll finish the "until". - bool done; - StackID cur_frame_zero_id; - - done = (m_stack_id < cur_frame_zero_id); - - if (done) - { - m_stepped_out = true; - SetPlanComplete(); - } - else - m_should_stop = false; - - if (this_site->GetNumberOfOwners() == 1) - m_explains_stop = true; - else - m_explains_stop = false; - return; - } + if (done) + SetPlanComplete(); else - { - // Check if we've hit one of our "until" breakpoints. - until_collection::iterator pos, end = m_until_points.end(); - for (pos = m_until_points.begin(); pos != end; pos++) - { - if (this_site->IsBreakpointAtThisSite ((*pos).second)) - { - // If we're at the right stack depth, then we're done. - - bool done; - StackID frame_zero_id = m_thread.GetStackFrameAtIndex(0)->GetStackID(); - - if (frame_zero_id == m_stack_id) - done = true; - else if (frame_zero_id < m_stack_id) - done = false; - else - { - StackFrameSP older_frame_sp = m_thread.GetStackFrameAtIndex(1); - - // But if we can't even unwind one frame we should just get out of here & stop... - if (older_frame_sp) - { - const SymbolContext &older_context - = older_frame_sp->GetSymbolContext(eSymbolContextEverything); - SymbolContext stack_context; - m_stack_id.GetSymbolContextScope()->CalculateSymbolContext(&stack_context); - - done = (older_context == stack_context); - } - else - done = false; - } - - if (done) - SetPlanComplete(); - else - m_should_stop = false; - - // Otherwise we've hit this breakpoint recursively. If we're the - // only breakpoint here, then we do explain the stop, and we'll continue. - // If not then we should let higher plans handle this stop. - if (this_site->GetNumberOfOwners() == 1) - m_explains_stop = true; - else - { - m_should_stop = true; - m_explains_stop = false; - } - return; - } - } + m_should_stop = false; + + // Otherwise we've hit this breakpoint recursively. If we're the + // only breakpoint here, then we do explain the stop, and we'll + // continue. + // If not then we should let higher plans handle this stop. + if (this_site->GetNumberOfOwners() == 1) + m_explains_stop = true; + else { + m_should_stop = true; + m_explains_stop = false; } - // If we get here we haven't hit any of our breakpoints, so let the higher - // plans take care of the stop. - m_explains_stop = false; return; + } } - else if (IsUsuallyUnexplainedStopReason(reason)) - { - m_explains_stop = false; - } - else - { - m_explains_stop = true; - } + } + // If we get here we haven't hit any of our breakpoints, so let the higher + // plans take care of the stop. + m_explains_stop = false; + return; + } else if (IsUsuallyUnexplainedStopReason(reason)) { + m_explains_stop = false; + } else { + m_explains_stop = true; } + } } -bool -ThreadPlanStepUntil::DoPlanExplainsStop (Event *event_ptr) -{ - // We don't explain signals or breakpoints (breakpoints that handle stepping in or - // out will be handled by a child plan. - AnalyzeStop(); - return m_explains_stop; +bool ThreadPlanStepUntil::DoPlanExplainsStop(Event *event_ptr) { + // We don't explain signals or breakpoints (breakpoints that handle stepping + // in or + // out will be handled by a child plan. + AnalyzeStop(); + return m_explains_stop; } -bool -ThreadPlanStepUntil::ShouldStop (Event *event_ptr) -{ - // If we've told our self in ExplainsStop that we plan to continue, then - // do so here. Otherwise, as long as this thread has stopped for a reason, - // we will stop. +bool ThreadPlanStepUntil::ShouldStop(Event *event_ptr) { + // If we've told our self in ExplainsStop that we plan to continue, then + // do so here. Otherwise, as long as this thread has stopped for a reason, + // we will stop. - StopInfoSP stop_info_sp = GetPrivateStopInfo (); - if (!stop_info_sp || stop_info_sp->GetStopReason() == eStopReasonNone) - return false; + StopInfoSP stop_info_sp = GetPrivateStopInfo(); + if (!stop_info_sp || stop_info_sp->GetStopReason() == eStopReasonNone) + return false; - AnalyzeStop(); - return m_should_stop; + AnalyzeStop(); + return m_should_stop; } -bool -ThreadPlanStepUntil::StopOthers () -{ - return m_stop_others; -} +bool ThreadPlanStepUntil::StopOthers() { return m_stop_others; } + +StateType ThreadPlanStepUntil::GetPlanRunState() { return eStateRunning; } + +bool ThreadPlanStepUntil::DoWillResume(StateType resume_state, + bool current_plan) { + if (current_plan) { + TargetSP target_sp(m_thread.CalculateTarget()); + if (target_sp) { + Breakpoint *return_bp = + target_sp->GetBreakpointByID(m_return_bp_id).get(); + if (return_bp != nullptr) + return_bp->SetEnabled(true); + + until_collection::iterator pos, end = m_until_points.end(); + for (pos = m_until_points.begin(); pos != end; pos++) { + Breakpoint *until_bp = + target_sp->GetBreakpointByID((*pos).second).get(); + if (until_bp != nullptr) + until_bp->SetEnabled(true); + } + } + } -StateType -ThreadPlanStepUntil::GetPlanRunState () -{ - return eStateRunning; + m_should_stop = true; + m_ran_analyze = false; + m_explains_stop = false; + return true; } -bool -ThreadPlanStepUntil::DoWillResume (StateType resume_state, bool current_plan) -{ - if (current_plan) - { - TargetSP target_sp (m_thread.CalculateTarget()); - if (target_sp) - { - Breakpoint *return_bp = target_sp->GetBreakpointByID(m_return_bp_id).get(); - if (return_bp != nullptr) - return_bp->SetEnabled (true); - - until_collection::iterator pos, end = m_until_points.end(); - for (pos = m_until_points.begin(); pos != end; pos++) - { - Breakpoint *until_bp = target_sp->GetBreakpointByID((*pos).second).get(); - if (until_bp != nullptr) - until_bp->SetEnabled (true); - } - } +bool ThreadPlanStepUntil::WillStop() { + TargetSP target_sp(m_thread.CalculateTarget()); + if (target_sp) { + Breakpoint *return_bp = target_sp->GetBreakpointByID(m_return_bp_id).get(); + if (return_bp != nullptr) + return_bp->SetEnabled(false); + + until_collection::iterator pos, end = m_until_points.end(); + for (pos = m_until_points.begin(); pos != end; pos++) { + Breakpoint *until_bp = target_sp->GetBreakpointByID((*pos).second).get(); + if (until_bp != nullptr) + until_bp->SetEnabled(false); } - - m_should_stop = true; - m_ran_analyze = false; - m_explains_stop = false; - return true; + } + return true; } -bool -ThreadPlanStepUntil::WillStop () -{ - TargetSP target_sp (m_thread.CalculateTarget()); - if (target_sp) - { - Breakpoint *return_bp = target_sp->GetBreakpointByID(m_return_bp_id).get(); - if (return_bp != nullptr) - return_bp->SetEnabled (false); - - until_collection::iterator pos, end = m_until_points.end(); - for (pos = m_until_points.begin(); pos != end; pos++) - { - Breakpoint *until_bp = target_sp->GetBreakpointByID((*pos).second).get(); - if (until_bp != nullptr) - until_bp->SetEnabled (false); - } - } - return true; -} +bool ThreadPlanStepUntil::MischiefManaged() { + // I'm letting "PlanExplainsStop" do all the work, and just reporting that + // here. + bool done = false; + if (IsPlanComplete()) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); + if (log) + log->Printf("Completed step until plan."); -bool -ThreadPlanStepUntil::MischiefManaged () -{ - // I'm letting "PlanExplainsStop" do all the work, and just reporting that here. - bool done = false; - if (IsPlanComplete()) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); - if (log) - log->Printf("Completed step until plan."); - - Clear(); - done = true; - } - if (done) - ThreadPlan::MischiefManaged (); + Clear(); + done = true; + } + if (done) + ThreadPlan::MischiefManaged(); - return done; + return done; } |