blob: 169d56ac9b647078d25522d40c9439903ad6ed7e [file] [log] [blame]
//===-- ExecutionContext.h --------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_TARGET_EXECUTIONCONTEXT_H
#define LLDB_TARGET_EXECUTIONCONTEXT_H
#include <mutex>
#include "lldb/Target/StackID.h"
#include "lldb/lldb-private.h"
namespace lldb_private {
//===----------------------------------------------------------------------===//
/// 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
/// objects: target, process, thread, and frame. Many objects in the debugger
/// need to track different executions contexts. For example, a local function
/// variable might have an execution context that refers to a stack frame. A
/// global or static variable might refer to a target since a stack frame
/// isn't required in order to evaluate a global or static variable (a process
/// isn't necessarily needed for a global variable since we might be able to
/// read the variable value from a data section in one of the object files in
/// a target). There are two types of objects that hold onto execution
/// contexts: ExecutionContextRef and ExecutionContext. Both of these objects
/// are described below.
///
/// Not all objects in an ExecutionContext objects will be valid. If you want
/// to refer strongly (ExecutionContext) or weakly (ExecutionContextRef) to a
/// process, then only the process and target references will be valid. For
/// threads, only the thread, process and target references will be filled in.
/// For frames, all of the objects will be filled in.
///
/// These classes are designed to be used as baton objects that get passed to
/// a wide variety of functions that require execution contexts.
//===----------------------------------------------------------------------===//
/// \class ExecutionContextRef ExecutionContext.h
/// "lldb/Target/ExecutionContext.h"
/// A class that holds a weak reference to an execution context.
///
/// ExecutionContextRef objects are designed to hold onto an execution context
/// that might change over time. For example, if an object wants to refer to a
/// stack frame, it should hold onto an ExecutionContextRef to a frame object.
/// The backing object that represents the stack frame might change over time
/// and instances of this object can track the logical object that refers to a
/// frame even if it does change.
///
/// These objects also don't keep execution objects around longer than they
/// should since they use weak pointers. For example if an object refers to a
/// stack frame and a stack frame is no longer in a thread, then a
/// ExecutionContextRef object that refers to that frame will not be able to
/// get a shared pointer to those objects since they are no longer around.
///
/// ExecutionContextRef objects can also be used as objects in classes that
/// want to track a "previous execution context". Since the weak references to
/// the execution objects (target, process, thread and frame) don't keep these
/// objects around, they are safe to keep around.
///
/// The general rule of thumb is all long lived objects that want to refer to
/// execution contexts should use ExecutionContextRef objects. The
/// ExecutionContext class is used to temporarily get shared pointers to any
/// execution context objects that are still around so they are guaranteed to
/// exist during a function that requires the objects. ExecutionContext
/// objects should NOT be used for long term storage since they will keep
/// objects alive with extra shared pointer references to these objects.
class ExecutionContextRef {
public:
/// Default Constructor.
ExecutionContextRef();
/// Copy Constructor.
ExecutionContextRef(const ExecutionContextRef &rhs);
/// Construct using an ExecutionContext object that might be nullptr.
///
/// If \a exe_ctx_ptr is valid, then make weak references to any valid
/// objects in the ExecutionContext, otherwise no weak references to any
/// execution context objects will be made.
ExecutionContextRef(const ExecutionContext *exe_ctx_ptr);
/// Construct using an ExecutionContext object.
///
/// Make weak references to any valid objects in the ExecutionContext.
ExecutionContextRef(const ExecutionContext &exe_ctx);
/// Construct using the target and all the selected items inside of it (the
/// process and its selected thread, and the thread's selected frame). If
/// there is no selected thread, default to the first thread If there is no
/// selected frame, default to the first frame.
ExecutionContextRef(Target *target, bool adopt_selected);
/// Construct using an execution context scope.
///
/// If the ExecutionContextScope object is valid and refers to a frame, make
/// weak references too the frame, thread, process and target. If the
/// ExecutionContextScope object is valid and refers to a thread, make weak
/// references too the thread, process and target. If the
/// ExecutionContextScope object is valid and refers to a process, make weak
/// references too the process and target. If the ExecutionContextScope
/// object is valid and refers to a target, make weak references too the
/// target.
ExecutionContextRef(ExecutionContextScope *exe_scope);
/// Construct using an execution context scope.
///
/// If the ExecutionContextScope object refers to a frame, make weak
/// references too the frame, thread, process and target. If the
/// ExecutionContextScope object refers to a thread, make weak references
/// too the thread, process and target. If the ExecutionContextScope object
/// refers to a process, make weak references too the process and target. If
/// the ExecutionContextScope object refers to a target, make weak
/// references too the target.
ExecutionContextRef(ExecutionContextScope &exe_scope);
~ExecutionContextRef();
/// Assignment operator
///
/// Copy all weak references in \a rhs.
ExecutionContextRef &operator=(const ExecutionContextRef &rhs);
/// Assignment operator from a ExecutionContext
///
/// Make weak references to any strongly referenced objects in \a exe_ctx.
ExecutionContextRef &operator=(const ExecutionContext &exe_ctx);
/// Clear the object's state.
///
/// Sets the process and thread to nullptr, and the frame index to an
/// invalid value.
void Clear();
/// Set accessor that creates a weak reference to the target referenced in
/// \a target_sp.
///
/// If \a target_sp is valid this object will create a weak reference to
/// that object, otherwise any previous target weak reference contained in
/// this object will be reset.
///
/// Only the weak reference to the target will be updated, no other weak
/// references will be modified. If you want this execution context to make
/// a weak reference to the target's process, use the
/// ExecutionContextRef::SetContext() functions.
///
/// \see ExecutionContextRef::SetContext(const lldb::TargetSP &, bool)
void SetTargetSP(const lldb::TargetSP &target_sp);
/// Set accessor that creates a weak reference to the process referenced in
/// \a process_sp.
///
/// If \a process_sp is valid this object will create a weak reference to
/// that object, otherwise any previous process weak reference contained in
/// this object will be reset.
///
/// Only the weak reference to the process will be updated, no other weak
/// references will be modified. If you want this execution context to make
/// a weak reference to the target, use the
/// ExecutionContextRef::SetContext() functions.
///
/// \see ExecutionContextRef::SetContext(const lldb::ProcessSP &)
void SetProcessSP(const lldb::ProcessSP &process_sp);
/// Set accessor that creates a weak reference to the thread referenced in
/// \a thread_sp.
///
/// If \a thread_sp is valid this object will create a weak reference to
/// that object, otherwise any previous thread weak reference contained in
/// this object will be reset.
///
/// Only the weak reference to the thread will be updated, no other weak
/// references will be modified. If you want this execution context to make
/// a weak reference to the thread's process and target, use the
/// ExecutionContextRef::SetContext() functions.
///
/// \see ExecutionContextRef::SetContext(const lldb::ThreadSP &)
void SetThreadSP(const lldb::ThreadSP &thread_sp);
/// Set accessor that creates a weak reference to the frame referenced in \a
/// frame_sp.
///
/// If \a frame_sp is valid this object will create a weak reference to that
/// object, otherwise any previous frame weak reference contained in this
/// object will be reset.
///
/// Only the weak reference to the frame will be updated, no other weak
/// references will be modified. If you want this execution context to make
/// a weak reference to the frame's thread, process and target, use the
/// ExecutionContextRef::SetContext() functions.
///
/// \see ExecutionContextRef::SetContext(const lldb::StackFrameSP &)
void SetFrameSP(const lldb::StackFrameSP &frame_sp);
void SetTargetPtr(Target *target, bool adopt_selected);
void SetProcessPtr(Process *process);
void SetThreadPtr(Thread *thread);
void SetFramePtr(StackFrame *frame);
/// Get accessor that creates a strong reference from the weak target
/// reference contained in this object.
///
/// \returns
/// A shared pointer to a target that is not guaranteed to be valid.
lldb::TargetSP GetTargetSP() const;
/// Get accessor that creates a strong reference from the weak process
/// reference contained in this object.
///
/// \returns
/// A shared pointer to a process that is not guaranteed to be valid.
lldb::ProcessSP GetProcessSP() const;
/// Get accessor that creates a strong reference from the weak thread
/// reference contained in this object.
///
/// \returns
/// A shared pointer to a thread that is not guaranteed to be valid.
lldb::ThreadSP GetThreadSP() const;
/// Get accessor that creates a strong reference from the weak frame
/// reference contained in this object.
///
/// \returns
/// A shared pointer to a frame that is not guaranteed to be valid.
lldb::StackFrameSP GetFrameSP() const;
/// Create an ExecutionContext object from this object.
///
/// Create strong references to any execution context objects that are still
/// valid. Any of the returned shared pointers in the ExecutionContext
/// objects is not guaranteed to be valid. \returns
/// An execution context object that has strong references to
/// any valid weak references in this object.
ExecutionContext Lock(bool thread_and_frame_only_if_stopped) const;
/// Returns true if this object has a weak reference to a thread. The return
/// value is only an indication of whether this object has a weak reference
/// and does not indicate whether the weak reference is valid or not.
bool HasThreadRef() const { return m_tid != LLDB_INVALID_THREAD_ID; }
/// Returns true if this object has a weak reference to a frame. The return
/// value is only an indication of whether this object has a weak reference
/// and does not indicate whether the weak reference is valid or not.
bool HasFrameRef() const { return m_stack_id.IsValid(); }
void ClearThread() {
m_thread_wp.reset();
m_tid = LLDB_INVALID_THREAD_ID;
}
void ClearFrame() { m_stack_id.Clear(); }
protected:
// Member variables
lldb::TargetWP m_target_wp; ///< A weak reference to a target
lldb::ProcessWP m_process_wp; ///< A weak reference to a process
mutable lldb::ThreadWP m_thread_wp; ///< A weak reference to a thread
lldb::tid_t m_tid; ///< The thread ID that this 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
};
/// \class ExecutionContext ExecutionContext.h
/// "lldb/Target/ExecutionContext.h"
/// A class that contains an execution context.
///
/// This baton object can be passed into any function that requires a context
/// that specifies a target, process, thread and frame. These objects are
/// designed to be used for short term execution context object storage while
/// a function might be trying to evaluate something that requires a thread or
/// frame. ExecutionContextRef objects can be used to initialize one of these
/// objects to turn the weak execution context object references to the
/// target, process, thread and frame into strong references (shared pointers)
/// so that functions can guarantee that these objects won't go away in the
/// middle of a function.
///
/// ExecutionContext objects should be used as short lived objects (typically
/// on the stack) in order to lock down an execution context for local use and
/// for passing down to other functions that also require specific contexts.
/// They should NOT be used for long term storage, for long term storage use
/// ExecutionContextRef objects.
class ExecutionContext {
public:
/// Default Constructor.
ExecutionContext();
// Copy constructor
ExecutionContext(const ExecutionContext &rhs);
// Adopt the target and optionally its current context.
ExecutionContext(Target *t, bool fill_current_process_thread_frame = true);
// Create execution contexts from shared pointers
ExecutionContext(const lldb::TargetSP &target_sp, bool get_process);
ExecutionContext(const lldb::ProcessSP &process_sp);
ExecutionContext(const lldb::ThreadSP &thread_sp);
ExecutionContext(const lldb::StackFrameSP &frame_sp);
// Create execution contexts from weak pointers
ExecutionContext(const lldb::TargetWP &target_wp, bool get_process);
ExecutionContext(const lldb::ProcessWP &process_wp);
ExecutionContext(const lldb::ThreadWP &thread_wp);
ExecutionContext(const lldb::StackFrameWP &frame_wp);
ExecutionContext(const ExecutionContextRef &exe_ctx_ref);
ExecutionContext(const ExecutionContextRef *exe_ctx_ref,
bool thread_and_frame_only_if_stopped = false);
// These two variants take in a locker, and grab the target, lock the API
// mutex into locker, then fill in the rest of the shared pointers.
ExecutionContext(const ExecutionContextRef &exe_ctx_ref,
std::unique_lock<std::recursive_mutex> &locker);
ExecutionContext(const ExecutionContextRef *exe_ctx_ref,
std::unique_lock<std::recursive_mutex> &locker);
// Create execution contexts from execution context scopes
ExecutionContext(ExecutionContextScope *exe_scope);
ExecutionContext(ExecutionContextScope &exe_scope);
/// Construct with process, thread, and frame index.
///
/// Initialize with process \a p, thread \a t, and frame index \a f.
///
/// \param[in] process
/// The process for this execution context.
///
/// \param[in] thread
/// The thread for this execution context.
///
/// \param[in] frame
/// The frame index for this execution context.
ExecutionContext(Process *process, Thread *thread = nullptr,
StackFrame *frame = nullptr);
~ExecutionContext();
ExecutionContext &operator=(const ExecutionContext &rhs);
bool operator==(const ExecutionContext &rhs) const;
bool operator!=(const ExecutionContext &rhs) const;
/// Clear the object's state.
///
/// Sets the process and thread to nullptr, and the frame index to an
/// invalid value.
void Clear();
RegisterContext *GetRegisterContext() const;
ExecutionContextScope *GetBestExecutionContextScope() const;
uint32_t GetAddressByteSize() const;
lldb::ByteOrder GetByteOrder() const;
/// Returns a pointer to the target object.
///
/// The returned pointer might be nullptr. Calling HasTargetScope(),
/// HasProcessScope(), HasThreadScope(), or HasFrameScope() can help to pre-
/// validate this pointer so that this accessor can freely be used without
/// having to check for nullptr each time.
///
/// \see ExecutionContext::HasTargetScope() const @see
/// ExecutionContext::HasProcessScope() const @see
/// ExecutionContext::HasThreadScope() const @see
/// ExecutionContext::HasFrameScope() const
Target *GetTargetPtr() const;
/// Returns a pointer to the process object.
///
/// The returned pointer might be nullptr. Calling HasProcessScope(),
/// HasThreadScope(), or HasFrameScope() can help to pre-validate this
/// pointer so that this accessor can freely be used without having to check
/// for nullptr each time.
///
/// \see ExecutionContext::HasProcessScope() const @see
/// ExecutionContext::HasThreadScope() const @see
/// ExecutionContext::HasFrameScope() const
Process *GetProcessPtr() const;
/// Returns a pointer to the thread object.
///
/// The returned pointer might be nullptr. Calling HasThreadScope() or
/// HasFrameScope() can help to pre-validate this pointer so that this
/// accessor can freely be used without having to check for nullptr each
/// time.
///
/// \see ExecutionContext::HasThreadScope() const @see
/// ExecutionContext::HasFrameScope() const
Thread *GetThreadPtr() const { return m_thread_sp.get(); }
/// Returns a pointer to the frame object.
///
/// The returned pointer might be nullptr. Calling HasFrameScope(), can help
/// to pre-validate this pointer so that this accessor can freely be used
/// without having to check for nullptr each time.
///
/// \see ExecutionContext::HasFrameScope() const
StackFrame *GetFramePtr() const { return m_frame_sp.get(); }
/// Returns a reference to the target object.
///
/// Clients should call HasTargetScope(), HasProcessScope(),
/// HasThreadScope(), or HasFrameScope() prior to calling this function to
/// ensure that this ExecutionContext object contains a valid target.
///
/// \see ExecutionContext::HasTargetScope() const @see
/// ExecutionContext::HasProcessScope() const @see
/// ExecutionContext::HasThreadScope() const @see
/// ExecutionContext::HasFrameScope() const
Target &GetTargetRef() const;
/// Returns a reference to the process object.
///
/// Clients should call HasProcessScope(), HasThreadScope(), or
/// HasFrameScope() prior to calling this function to ensure that this
/// ExecutionContext object contains a valid target.
///
/// \see ExecutionContext::HasProcessScope() const @see
/// ExecutionContext::HasThreadScope() const @see
/// ExecutionContext::HasFrameScope() const
Process &GetProcessRef() const;
/// Returns a reference to the thread object.
///
/// Clients should call HasThreadScope(), or HasFrameScope() prior to
/// calling this function to ensure that this ExecutionContext object
/// contains a valid target.
///
/// \see ExecutionContext::HasThreadScope() const @see
/// ExecutionContext::HasFrameScope() const
Thread &GetThreadRef() const;
/// Returns a reference to the thread object.
///
/// Clients should call HasFrameScope() prior to calling this function to
/// ensure that this ExecutionContext object contains a valid target.
///
/// \see ExecutionContext::HasFrameScope() const
StackFrame &GetFrameRef() const;
/// Get accessor to get the target shared pointer.
///
/// The returned shared pointer is not guaranteed to be valid.
const lldb::TargetSP &GetTargetSP() const { return m_target_sp; }
/// Get accessor to get the process shared pointer.
///
/// The returned shared pointer is not guaranteed to be valid.
const lldb::ProcessSP &GetProcessSP() const { return m_process_sp; }
/// Get accessor to get the thread shared pointer.
///
/// The returned shared pointer is not guaranteed to be valid.
const lldb::ThreadSP &GetThreadSP() const { return m_thread_sp; }
/// Get accessor to get the frame shared pointer.
///
/// The returned shared pointer is not guaranteed to be valid.
const lldb::StackFrameSP &GetFrameSP() const { return m_frame_sp; }
/// Set accessor to set only the target shared pointer.
void SetTargetSP(const lldb::TargetSP &target_sp);
/// Set accessor to set only the process shared pointer.
void SetProcessSP(const lldb::ProcessSP &process_sp);
/// Set accessor to set only the thread shared pointer.
void SetThreadSP(const lldb::ThreadSP &thread_sp);
/// Set accessor to set only the frame shared pointer.
void SetFrameSP(const lldb::StackFrameSP &frame_sp);
/// Set accessor to set only the target shared pointer from a target
/// pointer.
void SetTargetPtr(Target *target);
/// Set accessor to set only the process shared pointer from a process
/// pointer.
void SetProcessPtr(Process *process);
/// Set accessor to set only the thread shared pointer from a thread
/// pointer.
void SetThreadPtr(Thread *thread);
/// Set accessor to set only the frame shared pointer from a frame pointer.
void SetFramePtr(StackFrame *frame);
// Set the execution context using a target shared pointer.
//
// If "target_sp" is valid, sets the target context to match and if
// "get_process" is true, sets the process shared pointer if the target
// currently has a process.
void SetContext(const lldb::TargetSP &target_sp, bool get_process);
// Set the execution context using a process shared pointer.
//
// If "process_sp" is valid, then set the process and target in this context.
// Thread and frame contexts will be cleared. If "process_sp" is not valid,
// all shared pointers are reset.
void SetContext(const lldb::ProcessSP &process_sp);
// Set the execution context using a thread shared pointer.
//
// If "thread_sp" is valid, then set the thread, process and target in this
// context. The frame context will be cleared. If "thread_sp" is not valid,
// all shared pointers are reset.
void SetContext(const lldb::ThreadSP &thread_sp);
// Set the execution context using a frame shared pointer.
//
// If "frame_sp" is valid, then set the frame, thread, process and target in
// this context If "frame_sp" is not valid, all shared pointers are reset.
void SetContext(const lldb::StackFrameSP &frame_sp);
/// Returns true the ExecutionContext object contains a valid target.
///
/// This function can be called after initializing an ExecutionContext
/// object, and if it returns true, calls to GetTargetPtr() and
/// GetTargetRef() do not need to be checked for validity.
bool HasTargetScope() const;
/// Returns true the ExecutionContext object contains a valid target and
/// process.
///
/// This function can be called after initializing an ExecutionContext
/// object, and if it returns true, calls to GetTargetPtr() and
/// GetTargetRef(), GetProcessPtr(), and GetProcessRef(), do not need to be
/// checked for validity.
bool HasProcessScope() const;
/// Returns true the ExecutionContext object contains a valid target,
/// process, and thread.
///
/// This function can be called after initializing an ExecutionContext
/// object, and if it returns true, calls to GetTargetPtr(), GetTargetRef(),
/// GetProcessPtr(), GetProcessRef(), GetThreadPtr(), and GetThreadRef() do
/// not need to be checked for validity.
bool HasThreadScope() const;
/// Returns true the ExecutionContext object contains a valid target,
/// process, thread and frame.
///
/// This function can be called after initializing an ExecutionContext
/// object, and if it returns true, calls to GetTargetPtr(), GetTargetRef(),
/// GetProcessPtr(), GetProcessRef(), GetThreadPtr(), GetThreadRef(),
/// GetFramePtr(), and GetFrameRef() do not need to be checked for validity.
bool HasFrameScope() const;
protected:
// Member variables
lldb::TargetSP m_target_sp; ///< The target that owns the process/thread/frame
lldb::ProcessSP m_process_sp; ///< The process that owns the thread/frame
lldb::ThreadSP m_thread_sp; ///< The thread that owns the frame
lldb::StackFrameSP m_frame_sp; ///< The stack frame in thread.
};
} // namespace lldb_private
#endif // LLDB_TARGET_EXECUTIONCONTEXT_H