1818#include " lldb/Target/Process.h"
1919#include " lldb/Target/RegisterContext.h"
2020#include " lldb/Target/StackFrame.h"
21+ #include " lldb/Target/StackFrameRecognizer.h"
2122#include " lldb/Target/StopInfo.h"
2223#include " lldb/Target/Target.h"
2324#include " lldb/Target/Thread.h"
@@ -38,7 +39,7 @@ StackFrameList::StackFrameList(Thread &thread,
3839 const lldb::StackFrameListSP &prev_frames_sp,
3940 bool show_inline_frames)
4041 : m_thread(thread), m_prev_frames_sp(prev_frames_sp), m_mutex(), m_frames(),
41- m_selected_frame_idx(0 ), m_concrete_frames_fetched(0 ),
42+ m_selected_frame_idx(), m_concrete_frames_fetched(0 ),
4243 m_current_inlined_depth(UINT32_MAX),
4344 m_current_inlined_pc(LLDB_INVALID_ADDRESS),
4445 m_show_inlined_frames(show_inline_frames) {
@@ -252,7 +253,7 @@ struct CallDescriptor {
252253using CallSequence = std::vector<CallDescriptor>;
253254
254255// / Find the unique path through the call graph from \p begin (with return PC
255- // / \p return_pc) to \p end. On success this path is stored into \p path, and
256+ // / \p return_pc) to \p end. On success this path is stored into \p path, and
256257// / on failure \p path is unchanged.
257258static void FindInterveningFrames (Function &begin, Function &end,
258259 ExecutionContext &exe_ctx, Target &target,
@@ -776,9 +777,46 @@ bool StackFrameList::SetFrameAtIndex(uint32_t idx, StackFrameSP &frame_sp) {
776777 return false ; // resize failed, out of memory?
777778}
778779
779- uint32_t StackFrameList::GetSelectedFrameIndex () const {
780+ void StackFrameList::SelectMostRelevantFrame () {
781+ // Don't call into the frame recognizers on the private state thread as
782+ // they can cause code to run in the target, and that can cause deadlocks
783+ // when fetching stop events for the expression.
784+ if (m_thread.GetProcess ()->CurrentThreadIsPrivateStateThread ())
785+ return ;
786+
787+ Log *log = GetLog (LLDBLog::Thread);
788+
789+ // Only the top frame should be recognized.
790+ StackFrameSP frame_sp = GetFrameAtIndex (0 );
791+ if (!frame_sp) {
792+ LLDB_LOG (log, " Failed to construct Frame #0" );
793+ return ;
794+ }
795+
796+ RecognizedStackFrameSP recognized_frame_sp = frame_sp->GetRecognizedFrame ();
797+
798+ if (!recognized_frame_sp) {
799+ LLDB_LOG (log, " Frame #0 not recognized" );
800+ return ;
801+ }
802+
803+ if (StackFrameSP most_relevant_frame_sp =
804+ recognized_frame_sp->GetMostRelevantFrame ()) {
805+ LLDB_LOG (log, " Found most relevant frame at index {0}" ,
806+ most_relevant_frame_sp->GetFrameIndex ());
807+ SetSelectedFrame (most_relevant_frame_sp.get ());
808+ } else {
809+ LLDB_LOG (log, " No relevant frame!" );
810+ }
811+ }
812+
813+ uint32_t StackFrameList::GetSelectedFrameIndex () {
780814 std::lock_guard<std::recursive_mutex> guard (m_mutex);
781- return m_selected_frame_idx;
815+ if (!m_selected_frame_idx)
816+ SelectMostRelevantFrame ();
817+ if (!m_selected_frame_idx)
818+ m_selected_frame_idx = 0 ;
819+ return *m_selected_frame_idx;
782820}
783821
784822uint32_t StackFrameList::SetSelectedFrame (lldb_private::StackFrame *frame) {
@@ -787,17 +825,19 @@ uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
787825 const_iterator begin = m_frames.begin ();
788826 const_iterator end = m_frames.end ();
789827 m_selected_frame_idx = 0 ;
828+
790829 for (pos = begin; pos != end; ++pos) {
791830 if (pos->get () == frame) {
792831 m_selected_frame_idx = std::distance (begin, pos);
793832 uint32_t inlined_depth = GetCurrentInlinedDepth ();
794833 if (inlined_depth != UINT32_MAX)
795- m_selected_frame_idx -= inlined_depth;
834+ m_selected_frame_idx = *m_selected_frame_idx - inlined_depth;
796835 break ;
797836 }
798837 }
838+
799839 SetDefaultFileAndLineToSelectedFrame ();
800- return m_selected_frame_idx;
840+ return * m_selected_frame_idx;
801841}
802842
803843bool StackFrameList::SetSelectedFrameByIndex (uint32_t idx) {
@@ -825,10 +865,16 @@ void StackFrameList::SetDefaultFileAndLineToSelectedFrame() {
825865
826866// The thread has been run, reset the number stack frames to zero so we can
827867// determine how many frames we have lazily.
868+ // Note, we don't actually re-use StackFrameLists, we always make a new
869+ // StackFrameList every time we stop, and then copy frame information frame
870+ // by frame from the old to the new StackFrameList. So the comment above,
871+ // does not describe how StackFrameLists are currently used.
872+ // Clear is currently only used to clear the list in the destructor.
828873void StackFrameList::Clear () {
829874 std::lock_guard<std::recursive_mutex> guard (m_mutex);
830875 m_frames.clear ();
831876 m_concrete_frames_fetched = 0 ;
877+ m_selected_frame_idx.reset ();
832878}
833879
834880lldb::StackFrameSP
0 commit comments