diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -832,6 +832,7 @@ /// \see Thread:Suspend() Status Resume(); + /// Resume a process, and wait for it to stop. Status ResumeSynchronous(Stream *stream); /// Halts a running process. @@ -2167,12 +2168,17 @@ // process is hijacked and use_run_lock is true (the default), then this // function releases the run lock after the stop. Setting use_run_lock to // false will avoid this behavior. + // If we are waiting to stop that will return control to the user, + // then we also want to run SelectMostRelevantFrame, which is controlled + // by "select_most_relevant". lldb::StateType WaitForProcessToStop(const Timeout &timeout, lldb::EventSP *event_sp_ptr = nullptr, bool wait_always = true, lldb::ListenerSP hijack_listener = lldb::ListenerSP(), - Stream *stream = nullptr, bool use_run_lock = true); + Stream *stream = nullptr, bool use_run_lock = true, + SelectMostRelevant select_most_relevant = + DoNoSelectMostRelevantFrame); uint32_t GetIOHandlerID() const { return m_iohandler_sync.GetValue(); } @@ -2210,9 +2216,10 @@ /// \return /// \b true if the event describes a process state changed event, \b false /// otherwise. - static bool HandleProcessStateChangedEvent(const lldb::EventSP &event_sp, - Stream *stream, - bool &pop_process_io_handler); + static bool + HandleProcessStateChangedEvent(const lldb::EventSP &event_sp, Stream *stream, + SelectMostRelevant select_most_relevant, + bool &pop_process_io_handler); Event *PeekAtStateChangedEvents(); diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h --- a/lldb/include/lldb/Target/StackFrameList.h +++ b/lldb/include/lldb/Target/StackFrameList.h @@ -46,7 +46,15 @@ uint32_t SetSelectedFrame(lldb_private::StackFrame *frame); /// Get the currently selected frame index. - uint32_t GetSelectedFrameIndex(); + /// We should only call SelectMostRelevantFrame if (a) the user hasn't already + /// selected a frame, and (b) if this really is a user facing + /// "GetSelectedFrame". SMRF runs the frame recognizers which can do + /// arbitrary work that ends up being dangerous to do internally. Also, + /// for most internal uses we don't actually want the frame changed by the + /// SMRF logic. So unless this is in a command or SB API, you should + /// pass false here. + uint32_t + GetSelectedFrameIndex(SelectMostRelevant select_most_relevant_frame); /// Mark a stack frame as the currently selected frame using the frame index /// \p idx. Like \ref GetFrameAtIndex, invisible frames cannot be selected. diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -426,11 +426,16 @@ return lldb::StackFrameSP(); } - uint32_t GetSelectedFrameIndex() { - return GetStackFrameList()->GetSelectedFrameIndex(); + // Only pass true to select_most_relevant if you are fulfilling an explicit + // user request for GetSelectedFrameIndex. The most relevant frame is only + // for showing to the user, and can do arbitrary work, so we don't want to + // call it internally. + uint32_t GetSelectedFrameIndex(SelectMostRelevant select_most_relevant) { + return GetStackFrameList()->GetSelectedFrameIndex(select_most_relevant); } - lldb::StackFrameSP GetSelectedFrame(); + lldb::StackFrameSP + GetSelectedFrame(SelectMostRelevant select_most_relevant); uint32_t SetSelectedFrame(lldb_private::StackFrame *frame, bool broadcast = false); diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h --- a/lldb/include/lldb/lldb-private-enumerations.h +++ b/lldb/include/lldb/lldb-private-enumerations.h @@ -269,4 +269,9 @@ }; } +enum SelectMostRelevant : bool { + SelectMostRelevantFrame = true, + DoNoSelectMostRelevantFrame = false, +}; + #endif // LLDB_LLDB_PRIVATE_ENUMERATIONS_H diff --git a/lldb/source/API/SBThread.cpp b/lldb/source/API/SBThread.cpp --- a/lldb/source/API/SBThread.cpp +++ b/lldb/source/API/SBThread.cpp @@ -789,7 +789,11 @@ } if (!frame_sp) { - frame_sp = thread->GetSelectedFrame(); + // We don't want to run SelectMostRelevantFrame here, for instance if + // you called a sequence of StepOverUntil's you wouldn't want the + // frame changed out from under you because you stepped into a + // recognized frame. + frame_sp = thread->GetSelectedFrame(DoNoSelectMostRelevantFrame); if (!frame_sp) frame_sp = thread->GetStackFrameAtIndex(0); } @@ -1133,7 +1137,8 @@ if (exe_ctx.HasThreadScope()) { Process::StopLocker stop_locker; if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) { - frame_sp = exe_ctx.GetThreadPtr()->GetSelectedFrame(); + frame_sp = + exe_ctx.GetThreadPtr()->GetSelectedFrame(SelectMostRelevantFrame); sb_frame.SetFrameSP(frame_sp); } } diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -135,7 +135,7 @@ protected: bool DoExecute(Args &command, CommandReturnObject &result) override { Thread *thread = m_exe_ctx.GetThreadPtr(); - StackFrameSP frame_sp = thread->GetSelectedFrame(); + StackFrameSP frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame); ValueObjectSP valobj_sp; @@ -308,7 +308,7 @@ uint32_t frame_idx = UINT32_MAX; if (m_options.relative_frame_offset) { // The one and only argument is a signed relative frame index - frame_idx = thread->GetSelectedFrameIndex(); + frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame); if (frame_idx == UINT32_MAX) frame_idx = 0; @@ -362,7 +362,7 @@ return false; } } else if (command.GetArgumentCount() == 0) { - frame_idx = thread->GetSelectedFrameIndex(); + frame_idx = thread->GetSelectedFrameIndex(SelectMostRelevantFrame); if (frame_idx == UINT32_MAX) { frame_idx = 0; } @@ -372,7 +372,7 @@ bool success = thread->SetSelectedFrameByIndexNoisily( frame_idx, result.GetOutputStream()); if (success) { - m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + m_exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame)); result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat("Frame index (%u) out of range.\n", diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -556,8 +556,9 @@ } else if (m_step_type == eStepTypeOut) { new_plan_sp = thread->QueueThreadPlanForStepOut( abort_other_plans, nullptr, false, bool_stop_other_threads, eVoteYes, - eVoteNoOpinion, thread->GetSelectedFrameIndex(), new_plan_status, - m_options.m_step_out_avoid_no_debug); + eVoteNoOpinion, + thread->GetSelectedFrameIndex(DoNoSelectMostRelevantFrame), + new_plan_status, m_options.m_step_out_avoid_no_debug); } else if (m_step_type == eStepTypeScripted) { new_plan_sp = thread->QueueThreadPlanForStepScripted( abort_other_plans, m_class_options.GetName().c_str(), @@ -1527,7 +1528,8 @@ bool success = thread->SetSelectedFrameByIndexNoisily(0, result.GetOutputStream()); if (success) { - m_exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + m_exe_ctx.SetFrameSP( + thread->GetSelectedFrame(DoNoSelectMostRelevantFrame)); result.SetStatus(eReturnStatusSuccessFinishResult); } else { result.AppendErrorWithFormat( diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -2845,7 +2845,8 @@ return false; } - StackFrameSP frame_sp = thread->GetSelectedFrame(); + StackFrameSP frame_sp = + thread->GetSelectedFrame(DoNoSelectMostRelevantFrame); ValueObjectSP result_valobj_sp; EvaluateExpressionOptions options; lldb::ExpressionResults expr_result = target_sp->EvaluateExpression( diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp --- a/lldb/source/Core/Debugger.cpp +++ b/lldb/source/Core/Debugger.cpp @@ -1679,6 +1679,7 @@ // Display running state changes first before any STDIO if (got_state_changed && !state_is_stopped) { Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), + DoNoSelectMostRelevantFrame, pop_process_io_handler); } @@ -1718,6 +1719,7 @@ // Now display any stopped state changes after any STDIO if (got_state_changed && state_is_stopped) { Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), + DoNoSelectMostRelevantFrame, pop_process_io_handler); } diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp --- a/lldb/source/Core/IOHandlerCursesGUI.cpp +++ b/lldb/source/Core/IOHandlerCursesGUI.cpp @@ -5259,7 +5259,8 @@ for (size_t i = 0; i < num_threads; ++i) { ThreadSP thread = threads.GetThreadAtIndex(i); if (selected_thread->GetID() == thread->GetID()) { - selected_item = &root[i][thread->GetSelectedFrameIndex()]; + selected_item = + &root[i][thread->GetSelectedFrameIndex(SelectMostRelevantFrame)]; selection_index = selected_item->GetRowIndex(); return; } @@ -6411,7 +6412,8 @@ if (process && process->IsAlive() && StateIsStoppedState(process->GetState(), true)) { Thread *thread = exe_ctx.GetThreadPtr(); - uint32_t frame_idx = thread->GetSelectedFrameIndex(); + uint32_t frame_idx = + thread->GetSelectedFrameIndex(SelectMostRelevantFrame); exe_ctx.GetThreadRef().StepOut(frame_idx); } } @@ -6827,7 +6829,7 @@ if (process_alive) { thread = exe_ctx.GetThreadPtr(); if (thread) { - frame_sp = thread->GetSelectedFrame(); + frame_sp = thread->GetSelectedFrame(SelectMostRelevantFrame); auto tid = thread->GetID(); thread_changed = tid != m_tid; m_tid = tid; @@ -7374,7 +7376,8 @@ if (exe_ctx.HasThreadScope() && StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) { Thread *thread = exe_ctx.GetThreadPtr(); - uint32_t frame_idx = thread->GetSelectedFrameIndex(); + uint32_t frame_idx = + thread->GetSelectedFrameIndex(SelectMostRelevantFrame); exe_ctx.GetThreadRef().StepOut(frame_idx); } } @@ -7413,7 +7416,8 @@ m_debugger.GetCommandInterpreter().GetExecutionContext(); if (exe_ctx.HasThreadScope()) { Thread *thread = exe_ctx.GetThreadPtr(); - uint32_t frame_idx = thread->GetSelectedFrameIndex(); + uint32_t frame_idx = + thread->GetSelectedFrameIndex(SelectMostRelevantFrame); if (frame_idx == UINT32_MAX) frame_idx = 0; if (c == 'u' && frame_idx + 1 < thread->GetStackFrameCount()) @@ -7421,7 +7425,7 @@ else if (c == 'd' && frame_idx > 0) --frame_idx; if (thread->SetSelectedFrameByIndex(frame_idx, true)) - exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + exe_ctx.SetFrameSP(thread->GetSelectedFrame(SelectMostRelevantFrame)); } } return eKeyHandled; diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp --- a/lldb/source/Core/ValueObject.cpp +++ b/lldb/source/Core/ValueObject.cpp @@ -2852,7 +2852,7 @@ StackFrameSP frame_sp(exe_ctx.GetFrameSP()); if (!frame_sp) { if (use_selected) - frame_sp = thread_sp->GetSelectedFrame(); + frame_sp = thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); } if (frame_sp) m_exe_ctx_ref.SetFrameSP(frame_sp); diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp --- a/lldb/source/Expression/REPL.cpp +++ b/lldb/source/Expression/REPL.cpp @@ -233,7 +233,7 @@ ExecutionContext exe_ctx(m_target.GetProcessSP() ->GetThreadList() .GetSelectedThread() - ->GetSelectedFrame() + ->GetSelectedFrame(DoNoSelectMostRelevantFrame) .get()); lldb::ProcessSP process_sp(exe_ctx.GetProcessSP()); @@ -308,7 +308,8 @@ Thread *thread = exe_ctx.GetThreadPtr(); if (thread && thread->UnwindInnermostExpression().Success()) { thread->SetSelectedFrameByIndex(0, false); - exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + exe_ctx.SetFrameSP( + thread->GetSelectedFrame(DoNoSelectMostRelevantFrame)); } } diff --git a/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp b/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp --- a/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/ASan/InstrumentationRuntimeASan.cpp @@ -113,7 +113,8 @@ ThreadSP thread_sp = process_sp->GetThreadList().GetExpressionExecutionThread(); - StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + StackFrameSP frame_sp = + thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); if (!frame_sp) return StructuredData::ObjectSP(); diff --git a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp --- a/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/MainThreadChecker/InstrumentationRuntimeMainThreadChecker.cpp @@ -81,7 +81,8 @@ return StructuredData::ObjectSP(); ThreadSP thread_sp = exe_ctx_ref.GetThreadSP(); - StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + StackFrameSP frame_sp = + thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); ModuleSP runtime_module_sp = GetRuntimeModuleSP(); Target &target = process_sp->GetTarget(); diff --git a/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp b/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp --- a/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/TSan/InstrumentationRuntimeTSan.cpp @@ -303,7 +303,8 @@ return StructuredData::ObjectSP(); ThreadSP thread_sp = exe_ctx_ref.GetThreadSP(); - StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + StackFrameSP frame_sp = + thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); if (!frame_sp) return StructuredData::ObjectSP(); diff --git a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp --- a/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/UBSan/InstrumentationRuntimeUBSan.cpp @@ -108,7 +108,8 @@ return StructuredData::ObjectSP(); ThreadSP thread_sp = exe_ctx_ref.GetThreadSP(); - StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + StackFrameSP frame_sp = + thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); ModuleSP runtime_module_sp = GetRuntimeModuleSP(); Target &target = process_sp->GetTarget(); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -156,7 +156,7 @@ thread = exe_ctx.GetThreadPtr(); } if (thread) { - exe_ctx.SetFrameSP(thread->GetSelectedFrame()); + exe_ctx.SetFrameSP(thread->GetSelectedFrame(DoNoSelectMostRelevantFrame)); } } diff --git a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp --- a/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp +++ b/lldb/source/Plugins/MemoryHistory/asan/MemoryHistoryASan.cpp @@ -154,7 +154,8 @@ if (!thread_sp) return result; - StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + StackFrameSP frame_sp = + thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); if (!frame_sp) return result; diff --git a/lldb/source/Target/ExecutionContext.cpp b/lldb/source/Target/ExecutionContext.cpp --- a/lldb/source/Target/ExecutionContext.cpp +++ b/lldb/source/Target/ExecutionContext.cpp @@ -85,7 +85,8 @@ if (m_process_sp) { m_thread_sp = m_process_sp->GetThreadList().GetSelectedThread(); if (m_thread_sp) - m_frame_sp = m_thread_sp->GetSelectedFrame(); + m_frame_sp = + m_thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); } } } @@ -517,7 +518,8 @@ if (thread_sp) { SetThreadSP(thread_sp); - lldb::StackFrameSP frame_sp(thread_sp->GetSelectedFrame()); + lldb::StackFrameSP frame_sp( + thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame)); if (!frame_sp) frame_sp = thread_sp->GetStackFrameAtIndex(0); if (frame_sp) diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -1815,8 +1815,9 @@ nullptr); process_sp->RestoreProcessEvents(); bool pop_process_io_handler = false; - Process::HandleProcessStateChangedEvent(event_sp, stream, - pop_process_io_handler); + // This is a user-level stop, so we allow recognizers to select frames. + Process::HandleProcessStateChangedEvent( + event_sp, stream, SelectMostRelevantFrame, pop_process_io_handler); } return process_sp; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -644,10 +644,10 @@ } } -StateType Process::WaitForProcessToStop(const Timeout &timeout, - EventSP *event_sp_ptr, bool wait_always, - ListenerSP hijack_listener_sp, - Stream *stream, bool use_run_lock) { +StateType Process::WaitForProcessToStop( + const Timeout &timeout, EventSP *event_sp_ptr, bool wait_always, + ListenerSP hijack_listener_sp, Stream *stream, bool use_run_lock, + SelectMostRelevant select_most_relevant) { // We can't just wait for a "stopped" event, because the stopped event may // have restarted the target. We have to actually check each event, and in // the case of a stopped event check the restarted flag on the event. @@ -682,8 +682,8 @@ *event_sp_ptr = event_sp; bool pop_process_io_handler = (hijack_listener_sp.get() != nullptr); - Process::HandleProcessStateChangedEvent(event_sp, stream, - pop_process_io_handler); + Process::HandleProcessStateChangedEvent( + event_sp, stream, select_most_relevant, pop_process_io_handler); switch (state) { case eStateCrashed: @@ -712,9 +712,10 @@ return state; } -bool Process::HandleProcessStateChangedEvent(const EventSP &event_sp, - Stream *stream, - bool &pop_process_io_handler) { +bool Process::HandleProcessStateChangedEvent( + const EventSP &event_sp, Stream *stream, + SelectMostRelevant select_most_relevant, + bool &pop_process_io_handler) { const bool handle_pop = pop_process_io_handler; pop_process_io_handler = false; @@ -896,7 +897,8 @@ return false; const bool only_threads_with_stop_reason = true; - const uint32_t start_frame = thread_sp->GetSelectedFrameIndex(); + const uint32_t start_frame = + thread_sp->GetSelectedFrameIndex(select_most_relevant); const uint32_t num_frames = 1; const uint32_t num_frames_with_source = 1; const bool stop_format = true; @@ -1371,7 +1373,8 @@ Status error = PrivateResume(); if (error.Success()) { StateType state = - WaitForProcessToStop(std::nullopt, nullptr, true, listener_sp, stream); + WaitForProcessToStop(std::nullopt, nullptr, true, listener_sp, stream, + true /* use_run_lock */, SelectMostRelevantFrame); const bool must_be_alive = false; // eStateExited is ok, so this must be false if (!StateIsStoppedState(state, must_be_alive)) @@ -2649,7 +2652,8 @@ // Wait for a stopped event since we just posted one above... lldb::EventSP event_sp; StateType state = - WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp); + WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp, + nullptr, true, SelectMostRelevantFrame); if (!StateIsStoppedState(state, false)) { Log *log = GetLog(LLDBLog::Process); @@ -3154,9 +3158,13 @@ } // Wait for the process halt timeout seconds for the process to stop. - StateType state = - WaitForProcessToStop(GetInterruptTimeout(), &event_sp, true, - halt_listener_sp, nullptr, use_run_lock); + // If we are going to use the run lock, that means we're stopping out to the + // user, so we should also select the most relevant frame. + SelectMostRelevant select_most_relevant = + use_run_lock ? SelectMostRelevantFrame : DoNoSelectMostRelevantFrame; + StateType state = WaitForProcessToStop(GetInterruptTimeout(), &event_sp, true, + halt_listener_sp, nullptr, + use_run_lock, select_most_relevant); RestoreProcessEvents(); if (state == eStateInvalid || !event_sp) { @@ -4756,10 +4764,11 @@ // Save the thread & frame from the exe_ctx for restoration after we run const uint32_t thread_idx_id = thread->GetIndexID(); - StackFrameSP selected_frame_sp = thread->GetSelectedFrame(); + StackFrameSP selected_frame_sp = + thread->GetSelectedFrame(DoNoSelectMostRelevantFrame); if (!selected_frame_sp) { thread->SetSelectedFrame(nullptr); - selected_frame_sp = thread->GetSelectedFrame(); + selected_frame_sp = thread->GetSelectedFrame(DoNoSelectMostRelevantFrame); if (!selected_frame_sp) { diagnostic_manager.Printf( eDiagnosticSeverityError, @@ -4791,7 +4800,9 @@ StackID selected_stack_id; if (selected_thread_sp) { selected_tid = selected_thread_sp->GetIndexID(); - selected_stack_id = selected_thread_sp->GetSelectedFrame()->GetStackID(); + selected_stack_id = + selected_thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame) + ->GetStackID(); } else { selected_tid = LLDB_INVALID_THREAD_ID; } diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp --- a/lldb/source/Target/StackFrameList.cpp +++ b/lldb/source/Target/StackFrameList.cpp @@ -815,12 +815,18 @@ } } -uint32_t StackFrameList::GetSelectedFrameIndex() { +uint32_t StackFrameList::GetSelectedFrameIndex( + SelectMostRelevant select_most_relevant) { std::lock_guard guard(m_mutex); - if (!m_selected_frame_idx) + if (!m_selected_frame_idx && select_most_relevant) SelectMostRelevantFrame(); - if (!m_selected_frame_idx) + if (!m_selected_frame_idx) { + // If we aren't selecting the most relevant frame, and the selected frame + // isn't set, then don't force a selection here, just return 0. + if (!select_most_relevant) + return 0; m_selected_frame_idx = 0; + } return *m_selected_frame_idx; } @@ -858,7 +864,8 @@ void StackFrameList::SetDefaultFileAndLineToSelectedFrame() { if (m_thread.GetID() == m_thread.GetProcess()->GetThreadList().GetSelectedThread()->GetID()) { - StackFrameSP frame_sp(GetFrameAtIndex(GetSelectedFrameIndex())); + StackFrameSP frame_sp( + GetFrameAtIndex(GetSelectedFrameIndex(DoNoSelectMostRelevantFrame))); if (frame_sp) { SymbolContext sc = frame_sp->GetSymbolContext(eSymbolContextLineEntry); if (sc.line_entry.file) @@ -918,7 +925,8 @@ else last_frame = first_frame + num_frames; - StackFrameSP selected_frame_sp = m_thread.GetSelectedFrame(); + StackFrameSP selected_frame_sp = + m_thread.GetSelectedFrame(DoNoSelectMostRelevantFrame); const char *unselected_marker = nullptr; std::string buffer; if (selected_frame_marker) { diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -1456,7 +1456,8 @@ return ValueObjectSP(); } - StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); + StackFrameSP frame_sp = + thread_sp->GetSelectedFrame(DoNoSelectMostRelevantFrame); if (!frame_sp) { return ValueObjectSP(); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -3367,9 +3367,10 @@ if (async) { process_sp->RestoreProcessEvents(); } else { - state = process_sp->WaitForProcessToStop(std::nullopt, nullptr, false, - attach_info.GetHijackListener(), - stream); + // We are stopping all the way out to the user, so update selected frames. + state = process_sp->WaitForProcessToStop( + std::nullopt, nullptr, false, attach_info.GetHijackListener(), stream, + true, SelectMostRelevantFrame); process_sp->RestoreProcessEvents(); if (state != eStateStopped) { diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -263,10 +263,11 @@ new ThreadEventData(this->shared_from_this(), new_frame_id)); } -lldb::StackFrameSP Thread::GetSelectedFrame() { +lldb::StackFrameSP +Thread::GetSelectedFrame(SelectMostRelevant select_most_relevant) { StackFrameListSP stack_frame_list_sp(GetStackFrameList()); StackFrameSP frame_sp = stack_frame_list_sp->GetFrameAtIndex( - stack_frame_list_sp->GetSelectedFrameIndex()); + stack_frame_list_sp->GetSelectedFrameIndex(select_most_relevant)); FrameSelectedCallback(frame_sp.get()); return frame_sp; } @@ -297,7 +298,7 @@ const bool broadcast = true; bool success = SetSelectedFrameByIndex(frame_idx, broadcast); if (success) { - StackFrameSP frame_sp = GetSelectedFrame(); + StackFrameSP frame_sp = GetSelectedFrame(DoNoSelectMostRelevantFrame); if (frame_sp) { bool already_shown = false; SymbolContext frame_sc(