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
19 changes: 11 additions & 8 deletions lldb/include/lldb/Target/ExecutionContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@

#include "lldb/Host/ProcessRunLock.h"
#include "lldb/Target/StackID.h"
#include "lldb/Target/SyntheticFrameProvider.h"
#include "lldb/lldb-private.h"

namespace lldb_private {

struct StoppedExecutionContext;

//===----------------------------------------------------------------------===//
/// Execution context objects refer to objects in the execution of the program
/// that is being debugged. The consist of one or more of the following
Expand Down Expand Up @@ -270,9 +273,12 @@ class ExecutionContextRef {

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

friend llvm::Expected<StoppedExecutionContext>
GetStoppedExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr);

protected:
// Member variables
lldb::TargetWP m_target_wp; ///< A weak reference to a target
Expand All @@ -283,13 +289,10 @@ class ExecutionContextRef {
/// backing object changes
StackID m_stack_id; ///< The stack ID that this object refers to in case the
///< 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.
/// A map of identifiers to scripted frame providers used in this thread.
mutable std::optional<
std::pair<ScriptedFrameProviderDescriptor, lldb::frame_list_id_t>>
m_frame_list_id;
};

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

virtual lldb::RecognizedStackFrameSP GetRecognizedFrame();

/// Get the StackFrameList that contains this frame.
/// Get the identifier of the StackFrameList that contains this frame.
///
/// Returns the StackFrameList that contains this frame, allowing
/// Returns the StackFrameList identifier 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();
/// The identifier of the containing StackFrameList
lldb::frame_list_id_t GetContainingStackFrameListIdentifier() const {
return m_frame_list_id;
}

protected:
Expand Down Expand Up @@ -598,8 +598,8 @@ class StackFrame : public ExecutionContextScope,
/// be the first address of its function). True for actual frame zero as
/// well as any other frame with the same trait.
bool m_behaves_like_zeroth_frame;
lldb::frame_list_id_t m_frame_list_id = 0;
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
12 changes: 10 additions & 2 deletions lldb/include/lldb/Target/StackFrameList.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
public:
// Constructors and Destructors
StackFrameList(Thread &thread, const lldb::StackFrameListSP &prev_frames_sp,
bool show_inline_frames);
bool show_inline_frames,
lldb::frame_list_id_t provider_id = 0);

virtual ~StackFrameList();

Expand Down Expand Up @@ -104,6 +105,9 @@ class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
/// Get the thread associated with this frame list.
Thread &GetThread() const { return m_thread; }

/// Get the unique identifier for this frame list.
lldb::frame_list_id_t GetIdentifier() const { return m_identifier; }

protected:
friend class Thread;
friend class ScriptedFrameProvider;
Expand Down Expand Up @@ -212,6 +216,9 @@ class StackFrameList : public std::enable_shared_from_this<StackFrameList> {
/// Whether or not to show synthetic (inline) frames. Immutable.
const bool m_show_inlined_frames;

/// Unique identifier for this frame list instance.
lldb::frame_list_id_t m_identifier = 0;

/// Returns true if fetching frames was interrupted, false otherwise.
virtual bool FetchFramesUpTo(uint32_t end_idx,
InterruptionControl allow_interrupt);
Expand Down Expand Up @@ -244,7 +251,8 @@ class SyntheticStackFrameList : public StackFrameList {
SyntheticStackFrameList(Thread &thread, lldb::StackFrameListSP input_frames,
const lldb::StackFrameListSP &prev_frames_sp,
bool show_inline_frames,
lldb::SyntheticFrameProviderSP provider_sp);
lldb::SyntheticFrameProviderSP provider_sp,
uint64_t provider_id);

protected:
/// Override FetchFramesUpTo to lazily return frames from the provider
Expand Down
31 changes: 28 additions & 3 deletions lldb/include/lldb/Target/Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/RegisterCheckpoint.h"
#include "lldb/Target/StackFrameList.h"
#include "lldb/Target/SyntheticFrameProvider.h"
#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/Event.h"
#include "lldb/Utility/StructuredData.h"
#include "lldb/Utility/UnimplementedError.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/MemoryBuffer.h"

#define LLDB_THREAD_MAX_STOP_EXC_DATA 8
Expand Down Expand Up @@ -1297,12 +1299,18 @@ class Thread : public std::enable_shared_from_this<Thread>,

lldb::StackFrameListSP GetStackFrameList();

/// Get a frame list by its unique identifier.
lldb::StackFrameListSP GetFrameListByIdentifier(lldb::frame_list_id_t id);

llvm::Error
LoadScriptedFrameProvider(const ScriptedFrameProviderDescriptor &descriptor);

llvm::Expected<ScriptedFrameProviderDescriptor>
GetScriptedFrameProviderDescriptorForID(lldb::frame_list_id_t id) const;

void ClearScriptedFrameProvider();

const llvm::SmallVector<lldb::SyntheticFrameProviderSP, 0> &
const llvm::DenseMap<lldb::frame_list_id_t, lldb::SyntheticFrameProviderSP> &
GetFrameProviders() const {
return m_frame_providers;
}
Expand Down Expand Up @@ -1384,6 +1392,8 @@ class Thread : public std::enable_shared_from_this<Thread>,
m_state_mutex; ///< Multithreaded protection for m_state.
mutable std::recursive_mutex
m_frame_mutex; ///< Multithreaded protection for m_state.
lldb::StackFrameListSP
m_unwinder_frames_sp; ///< The unwinder frame list (ID 0).
lldb::StackFrameListSP m_curr_frames_sp; ///< The stack frames that get lazily
///populated after a thread stops.
lldb::StackFrameListSP m_prev_frames_sp; ///< The previous stack frames from
Expand All @@ -1410,8 +1420,23 @@ class Thread : public std::enable_shared_from_this<Thread>,
/// The Thread backed by this thread, if any.
lldb::ThreadWP m_backed_thread;

/// The Scripted Frame Providers for this thread.
llvm::SmallVector<lldb::SyntheticFrameProviderSP, 0> m_frame_providers;
/// Map from frame list ID to its frame provider.
/// Cleared in ClearStackFrames(), repopulated in GetStackFrameList().
llvm::DenseMap<lldb::frame_list_id_t, lldb::SyntheticFrameProviderSP>
m_frame_providers;

/// Ordered chain of provider IDs.
/// Persists across ClearStackFrames() to maintain stable provider IDs.
std::vector<std::pair<ScriptedFrameProviderDescriptor, lldb::frame_list_id_t>>
m_provider_chain_ids;

/// Map from frame list identifier to frame list weak pointer.
mutable llvm::DenseMap<lldb::frame_list_id_t, lldb::StackFrameListWP>
m_frame_lists_by_id;

/// Counter for assigning unique provider IDs. Starts at 1 since 0 is
/// reserved for normal unwinder frames. Persists across ClearStackFrames.
lldb::frame_list_id_t m_next_provider_id = 1;

private:
bool m_extended_info_fetched; // Have we tried to retrieve the m_extended_info
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/lldb-defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
#define LLDB_INVALID_PROCESS_ID 0
#define LLDB_INVALID_THREAD_ID 0
#define LLDB_INVALID_FRAME_ID UINT32_MAX
#define LLDB_UNWINDER_FRAME_LIST_ID 0
#define LLDB_INVALID_SIGNAL_NUMBER INT32_MAX
#define LLDB_INVALID_SYMBOL_ID UINT32_MAX
#define LLDB_INVALID_OFFSET UINT64_MAX // Must match max of lldb::offset_t
Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/lldb-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ typedef uint64_t user_id_t;
typedef uint64_t pid_t;
typedef uint64_t tid_t;
typedef uint64_t offset_t;
typedef uint32_t frame_list_id_t;
typedef int32_t break_id_t;
typedef int32_t watch_id_t;
typedef uint32_t wp_resource_id_t;
Expand Down
74 changes: 56 additions & 18 deletions lldb/source/Target/ExecutionContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,15 @@ lldb_private::GetStoppedExecutionContext(

auto thread_sp = exe_ctx_ref_ptr->GetThreadSP();
auto frame_sp = exe_ctx_ref_ptr->GetFrameSP();

if (!frame_sp && exe_ctx_ref_ptr->m_frame_list_id) {
return llvm::createStringError(
"attempted to create a StoppedExecutionContext but "
"ScriptedFrameProvider (name = %s - id = %u) is no longer available",
exe_ctx_ref_ptr->m_frame_list_id->first.GetName().str().c_str(),
exe_ctx_ref_ptr->m_frame_list_id->second);
}

return StoppedExecutionContext(target_sp, process_sp, thread_sp, frame_sp,
std::move(api_lock), std::move(stop_locker));
}
Expand Down Expand Up @@ -466,12 +475,25 @@ operator=(const ExecutionContext &exe_ctx) {
else
m_tid = LLDB_INVALID_THREAD_ID;
lldb::StackFrameSP frame_sp(exe_ctx.GetFrameSP());
if (frame_sp) {
m_stack_id = frame_sp->GetStackID();
m_frame_list_wp = frame_sp->GetContainingStackFrameList();

if (frame_sp && thread_sp) {
lldb::frame_list_id_t frame_list_id =
frame_sp->GetContainingStackFrameListIdentifier();
auto frame_list_descriptor_or_err =
thread_sp->GetScriptedFrameProviderDescriptorForID(frame_list_id);
if (frame_list_descriptor_or_err) {
m_stack_id = frame_sp->GetStackID();
m_frame_list_id = {*frame_list_descriptor_or_err, frame_list_id};
} else {
LLDB_LOG_ERROR(GetLog(LLDBLog::Process),
frame_list_descriptor_or_err.takeError(),
"Failed to fetch scripted frame provider descriptor: {0}");
m_stack_id.Clear();
m_frame_list_id.reset();
}
} else {
m_stack_id.Clear();
m_frame_list_wp.reset();
m_frame_list_id.reset();
}
return *this;
}
Expand Down Expand Up @@ -512,11 +534,25 @@ void ExecutionContextRef::SetThreadSP(const lldb::ThreadSP &thread_sp) {
}

void ExecutionContextRef::SetFrameSP(const lldb::StackFrameSP &frame_sp) {
if (frame_sp) {
if (!frame_sp) {
Clear();
return;
}

lldb::ThreadSP thread_sp = frame_sp->GetThread();
lldb::frame_list_id_t frame_list_id =
frame_sp->GetContainingStackFrameListIdentifier();
auto frame_list_descriptor_or_err =
thread_sp->GetScriptedFrameProviderDescriptorForID(frame_list_id);

if (frame_list_descriptor_or_err) {
m_stack_id = frame_sp->GetStackID();
m_frame_list_wp = frame_sp->GetContainingStackFrameList();
SetThreadSP(frame_sp->GetThread());
m_frame_list_id = {*frame_list_descriptor_or_err, frame_list_id};
SetThreadSP(thread_sp);
} else {
LLDB_LOG_ERROR(GetLog(LLDBLog::Process),
frame_list_descriptor_or_err.takeError(),
"Failed to fetch scripted frame provider descriptor: {0}");
ClearFrame();
ClearThread();
m_process_wp.reset();
Expand Down Expand Up @@ -641,21 +677,23 @@ 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()) {
lldb::ThreadSP thread_sp(GetThreadSP());
if (!thread_sp || !m_stack_id.IsValid())
return lldb::StackFrameSP();

// Try the remembered frame list first to avoid circular dependencies
// during frame provider initialization.
if (m_frame_list_id) {
if (auto frame_list_sp =
thread_sp->GetFrameListByIdentifier(m_frame_list_id->second)) {
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);
}
return lldb::StackFrameSP();

// Fallback: ask the thread, which might re-trigger the frame provider
// initialization.
return thread_sp->GetFrameWithStackID(m_stack_id);
}

ExecutionContext
Expand Down
Loading
Loading