diff options
Diffstat (limited to 'lldb/source/Target')
-rw-r--r-- | lldb/source/Target/Process.cpp | 16 | ||||
-rw-r--r-- | lldb/source/Target/StopInfo.cpp | 18 | ||||
-rw-r--r-- | lldb/source/Target/Thread.cpp | 65 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepInstruction.cpp | 9 | ||||
-rw-r--r-- | lldb/source/Target/ThreadPlanStepRange.cpp | 10 |
5 files changed, 91 insertions, 27 deletions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index c1a518cad78..f68a67c706a 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -5227,15 +5227,9 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, do_resume = false; handle_running_event = true; } else { - StopInfoSP stop_info_sp(thread_sp->GetStopInfo()); - StopReason stop_reason = eStopReasonInvalid; - if (stop_info_sp) - stop_reason = stop_info_sp->GetStopReason(); - - // FIXME: We only check if the stop reason is plan complete, - // should we make sure that - // it is OUR plan that is complete? - if (stop_reason == eStopReasonPlanComplete) { + ThreadPlanSP plan = thread->GetCompletedPlan(); + if (plan == thread_plan_sp && plan->PlanSucceeded()) { + if (log) log->PutCString("Process::RunThreadPlan(): execution " "completed successfully."); @@ -5246,9 +5240,11 @@ Process::RunThreadPlan(ExecutionContext &exe_ctx, return_value = eExpressionCompleted; } else { + StopInfoSP stop_info_sp = thread_sp->GetStopInfo(); // Something restarted the target, so just wait for it to // stop for real. - if (stop_reason == eStopReasonBreakpoint) { + if (stop_info_sp && + stop_info_sp->GetStopReason() == eStopReasonBreakpoint) { if (log) log->Printf("Process::RunThreadPlan() stopped for " "breakpoint: %s.", diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp index 89081f34834..185ff4dee88 100644 --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -269,6 +269,7 @@ protected: if (!m_should_perform_action) return; m_should_perform_action = false; + bool internal_breakpoint = true; ThreadSP thread_sp(m_thread_wp.lock()); @@ -495,6 +496,9 @@ protected: if (callback_says_stop) m_should_stop = true; + if (m_should_stop && !bp_loc_sp->GetBreakpoint().IsInternal()) + internal_breakpoint = false; + // If we are going to stop for this breakpoint, then remove the // breakpoint. if (callback_says_stop && bp_loc_sp && @@ -526,6 +530,20 @@ protected: "Process::%s could not find breakpoint site id: %" PRId64 "...", __FUNCTION__, m_value); } + + if ((m_should_stop == false || internal_breakpoint) + && thread_sp->CompletedPlanOverridesBreakpoint()) { + + // Override should_stop decision when we have + // completed step plan additionally to the breakpoint + m_should_stop = true; + + // Here we clean the preset stop info so the next + // GetStopInfo call will find the appropriate stop info, + // which should be the stop info related to the completed plan + thread_sp->ResetStopInfo(); + } + if (log) log->Printf("Process::%s returning from action with m_should_stop: %d.", __FUNCTION__, m_should_stop); diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 7b2772e0400..fb702fd3ae6 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -380,24 +380,32 @@ lldb::StopInfoSP Thread::GetStopInfo() { if (m_destroy_called) return m_stop_info_sp; - ThreadPlanSP plan_sp(GetCompletedPlan()); + ThreadPlanSP completed_plan_sp(GetCompletedPlan()); ProcessSP process_sp(GetProcess()); const uint32_t stop_id = process_sp ? process_sp->GetStopID() : UINT32_MAX; - if (plan_sp && plan_sp->PlanSucceeded()) { - return StopInfo::CreateStopReasonWithPlan(plan_sp, GetReturnValueObject(), - GetExpressionVariable()); + + // Here we select the stop info according to priorirty: + // - m_stop_info_sp (if not trace) - preset value + // - completed plan stop info - new value with plan from completed plan stack + // - m_stop_info_sp (trace stop reason is OK now) + // - ask GetPrivateStopInfo to set stop info + + bool have_valid_stop_info = m_stop_info_sp && + m_stop_info_sp ->IsValid() && + m_stop_info_stop_id == stop_id; + bool have_valid_completed_plan = completed_plan_sp && completed_plan_sp->PlanSucceeded(); + bool plan_overrides_trace = + have_valid_stop_info && have_valid_completed_plan + && (m_stop_info_sp->GetStopReason() == eStopReasonTrace); + + if (have_valid_stop_info && !plan_overrides_trace) { + return m_stop_info_sp; + } else if (have_valid_completed_plan) { + return StopInfo::CreateStopReasonWithPlan( + completed_plan_sp, GetReturnValueObject(), GetExpressionVariable()); } else { - if ((m_stop_info_stop_id == stop_id) || // Stop info is valid, just return - // what we have (even if empty) - (m_stop_info_sp && - m_stop_info_sp - ->IsValid())) // Stop info is valid, just return what we have - { - return m_stop_info_sp; - } else { - GetPrivateStopInfo(); - return m_stop_info_sp; - } + GetPrivateStopInfo(); + return m_stop_info_sp; } } @@ -459,6 +467,12 @@ bool Thread::StopInfoIsUpToDate() const { // date... } +void Thread::ResetStopInfo() { + if (m_stop_info_sp) { + m_stop_info_sp.reset(); + } +} + void Thread::SetStopInfo(const lldb::StopInfoSP &stop_info_sp) { m_stop_info_sp = stop_info_sp; if (m_stop_info_sp) { @@ -526,7 +540,8 @@ bool Thread::CheckpointThreadState(ThreadStateCheckpoint &saved_state) { if (process_sp) saved_state.orig_stop_id = process_sp->GetStopID(); saved_state.current_inlined_depth = GetCurrentInlinedDepth(); - + saved_state.m_completed_plan_stack = m_completed_plan_stack; + return true; } @@ -559,6 +574,7 @@ bool Thread::RestoreThreadStateFromCheckpoint( SetStopInfo(saved_state.stop_info_sp); GetStackFrameList()->SetCurrentInlinedDepth( saved_state.current_inlined_depth); + m_completed_plan_stack = saved_state.m_completed_plan_stack; return true; } @@ -895,6 +911,9 @@ bool Thread::ShouldStop(Event *event_ptr) { if (should_stop) { ThreadPlan *plan_ptr = GetCurrentPlan(); + + // Discard the stale plans and all plans below them in the stack, + // plus move the completed plans to the completed plan stack while (!PlanIsBasePlan(plan_ptr)) { bool stale = plan_ptr->IsPlanStale(); ThreadPlan *examined_plan = plan_ptr; @@ -905,7 +924,15 @@ bool Thread::ShouldStop(Event *event_ptr) { log->Printf( "Plan %s being discarded in cleanup, it says it is already done.", examined_plan->GetName()); - DiscardThreadPlansUpToPlan(examined_plan); + while (GetCurrentPlan() != examined_plan) { + DiscardPlan(); + } + if (examined_plan->IsPlanComplete()) { + // plan is complete but does not explain the stop (example: step to a line + // with breakpoint), let us move the plan to completed_plan_stack anyway + PopPlan(); + } else + DiscardPlan(); } } } @@ -1133,6 +1160,10 @@ bool Thread::WasThreadPlanDiscarded(ThreadPlan *plan) { return false; } +bool Thread::CompletedPlanOverridesBreakpoint() { + return (!m_completed_plan_stack.empty()) ; +} + ThreadPlan *Thread::GetPreviousPlan(ThreadPlan *current_plan) { if (current_plan == nullptr) return nullptr; diff --git a/lldb/source/Target/ThreadPlanStepInstruction.cpp b/lldb/source/Target/ThreadPlanStepInstruction.cpp index ff11ec02ece..c3ee0b27e82 100644 --- a/lldb/source/Target/ThreadPlanStepInstruction.cpp +++ b/lldb/source/Target/ThreadPlanStepInstruction.cpp @@ -94,6 +94,15 @@ 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) { + // Set plan Complete when we reach next instruction + uint64_t pc = m_thread.GetRegisterContext()->GetPC(0); + uint32_t max_opcode_size = m_thread.CalculateTarget() + ->GetArchitecture().GetMaximumOpcodeByteSize(); + bool next_instruction_reached = (pc > m_instruction_addr) && + (pc <= m_instruction_addr + max_opcode_size); + if (next_instruction_reached) { + SetPlanComplete(); + } return (m_thread.GetRegisterContext()->GetPC(0) != m_instruction_addr); } else if (cur_frame_id < m_stack_id) { // If the current frame is younger than the start frame and we are stepping diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp index 1647d854641..5398b26fb67 100644 --- a/lldb/source/Target/ThreadPlanStepRange.cpp +++ b/lldb/source/Target/ThreadPlanStepRange.cpp @@ -461,6 +461,16 @@ bool ThreadPlanStepRange::IsPlanStale() { // One tricky bit here is that some stubs don't push a frame, so we should. // check that we are in the same symbol. if (!InRange()) { + // Set plan Complete when we reach next instruction just after the range + lldb::addr_t addr = m_thread.GetRegisterContext()->GetPC() - 1; + size_t num_ranges = m_address_ranges.size(); + for (size_t i = 0; i < num_ranges; i++) { + bool in_range = m_address_ranges[i].ContainsLoadAddress( + addr, m_thread.CalculateTarget().get()); + if (in_range) { + SetPlanComplete(); + } + } return true; } } |