Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions lldb/include/lldb/Target/ExecutionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,10 @@ class ExecutionContextRef {
m_tid = LLDB_INVALID_THREAD_ID;
}

void ClearFrame() { m_stack_id.Clear(); }
void ClearFrame() {
m_stack_id.Clear();
m_frame_list_wp.reset();
}

protected:
// Member variables
Expand All @@ -279,7 +282,14 @@ class ExecutionContextRef {
///< object refers to in case the
/// backing object changes
StackID m_stack_id; ///< The stack ID that this object refers to in case the
///backing object changes
///< backing object changes
mutable lldb::StackFrameListWP
m_frame_list_wp; ///< Weak reference to the
///< frame list that contains
///< this frame. If we can create a valid
///< StackFrameListSP from it, we must use it to resolve
///< the StackID, otherwise, we should ask the Thread's
///< StackFrameList.
};

/// \class ExecutionContext ExecutionContext.h
Expand Down
14 changes: 14 additions & 0 deletions lldb/include/lldb/Target/StackFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,19 @@ class StackFrame : public ExecutionContextScope,

lldb::RecognizedStackFrameSP GetRecognizedFrame();

/// Get the StackFrameList that contains this frame.
///
/// Returns the StackFrameList that contains this frame, allowing
/// frames to resolve execution contexts without calling
/// Thread::GetStackFrameList(), which can cause circular dependencies
/// during frame provider initialization.
///
/// \return
/// The StackFrameList that contains this frame, or nullptr if not set.
virtual lldb::StackFrameListSP GetContainingStackFrameList() const {
return m_frame_list_wp.lock();
}

protected:
friend class StackFrameList;

Expand Down Expand Up @@ -574,6 +587,7 @@ class StackFrame : public ExecutionContextScope,
/// well as any other frame with the same trait.
bool m_behaves_like_zeroth_frame;
lldb::VariableListSP m_variable_list_sp;
lldb::StackFrameListWP m_frame_list_wp;
/// Value objects for each variable in m_variable_list_sp.
ValueObjectList m_variable_list_value_objects;
std::optional<lldb::RecognizedStackFrameSP> m_recognized_frame_sp;
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Target/StackFrameList.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace lldb_private {

class ScriptedThread;

class StackFrameList {
class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
public:
// Constructors and Destructors
StackFrameList(Thread &thread, const lldb::StackFrameListSP &prev_frames_sp,
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/lldb-forward.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ typedef std::unique_ptr<lldb_private::SourceManager> SourceManagerUP;
typedef std::shared_ptr<lldb_private::StackFrame> StackFrameSP;
typedef std::weak_ptr<lldb_private::StackFrame> StackFrameWP;
typedef std::shared_ptr<lldb_private::StackFrameList> StackFrameListSP;
typedef std::weak_ptr<lldb_private::StackFrameList> StackFrameListWP;
typedef std::shared_ptr<lldb_private::StackFrameRecognizer>
StackFrameRecognizerSP;
typedef std::unique_ptr<lldb_private::StackFrameRecognizerManager>
Expand Down
17 changes: 15 additions & 2 deletions lldb/source/Target/ExecutionContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,10 +466,13 @@ operator=(const ExecutionContext &exe_ctx) {
else
m_tid = LLDB_INVALID_THREAD_ID;
lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());
if (frame_sp)
if (frame_sp) {
m_stack_id = frame_sp->GetStackID();
else
m_frame_list_wp = frame_sp->GetContainingStackFrameList();
} else {
m_stack_id.Clear();
m_frame_list_wp.reset();
}
return *this;
}

Expand Down Expand Up @@ -511,6 +514,7 @@ void ExecutionContextRef::SetThreadSP(const lldb::ThreadSP &thread_sp) {
void ExecutionContextRef::SetFrameSP(const lldb::StackFrameSP &frame_sp) {
if (frame_sp) {
m_stack_id = frame_sp->GetStackID();
m_frame_list_wp = frame_sp->GetContainingStackFrameList();
SetThreadSP(frame_sp->GetThread());
} else {
ClearFrame();
Expand Down Expand Up @@ -638,6 +642,15 @@ lldb::ThreadSP ExecutionContextRef::GetThreadSP() const {

lldb::StackFrameSP ExecutionContextRef::GetFrameSP() const {
if (m_stack_id.IsValid()) {
// Try the remembered frame list first to avoid circular dependencies
// during frame provider initialization.
if (auto frame_list_sp = m_frame_list_wp.lock()) {
if (auto frame_sp = frame_list_sp->GetFrameWithStackID(m_stack_id))
return frame_sp;
}

// Fallback: ask the thread, which might re-trigger the frame provider
// initialization.
lldb::ThreadSP thread_sp(GetThreadSP());
if (thread_sp)
return thread_sp->GetFrameWithStackID(m_stack_id);
Expand Down
5 changes: 5 additions & 0 deletions lldb/source/Target/StackFrameList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ void StackFrameList::SynthesizeTailCallFrames(StackFrame &next_frame) {
m_thread.shared_from_this(), frame_idx, concrete_frame_idx, cfa,
cfa_is_valid, pc, StackFrame::Kind::Regular, artificial,
behaves_like_zeroth_frame, &sc);
synth_frame->m_frame_list_wp = shared_from_this();
m_frames.push_back(synth_frame);
LLDB_LOG(log, "Pushed frame {0} at {1:x}", callee->GetDisplayName(), pc);
}
Expand Down Expand Up @@ -445,6 +446,7 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
unwind_frame_sp = std::make_shared<StackFrame>(
m_thread.shared_from_this(), m_frames.size(), idx, reg_ctx_sp,
cfa, pc, behaves_like_zeroth_frame, nullptr);
unwind_frame_sp->m_frame_list_wp = shared_from_this();
m_frames.push_back(unwind_frame_sp);
}
} else {
Expand Down Expand Up @@ -479,6 +481,7 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
// although its concrete index will stay the same.
SynthesizeTailCallFrames(*unwind_frame_sp.get());

unwind_frame_sp->m_frame_list_wp = shared_from_this();
m_frames.push_back(unwind_frame_sp);
}

Expand All @@ -503,6 +506,7 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
unwind_frame_sp->GetRegisterContextSP(), cfa, next_frame_address,
behaves_like_zeroth_frame, &next_frame_sc));

frame_sp->m_frame_list_wp = shared_from_this();
m_frames.push_back(frame_sp);
unwind_sc = next_frame_sc;
curr_frame_address = next_frame_address;
Expand Down Expand Up @@ -559,6 +563,7 @@ bool StackFrameList::FetchFramesUpTo(uint32_t end_idx,
prev_frame->UpdatePreviousFrameFromCurrentFrame(*curr_frame);
// Now copy the fixed up previous frame into the current frames so the
// pointer doesn't change.
prev_frame_sp->m_frame_list_wp = shared_from_this();
m_frames[curr_frame_idx] = prev_frame_sp;

#if defined(DEBUG_STACK_FRAMES)
Expand Down
Loading