//===-- ExecutionContext.h --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// 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 deascribed below. /// /// Not all objects in an ExectionContext objects will be valid. If you want /// to refer stronly (ExectionContext) or weakly (ExectionContextRef) 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. //===----------------------------------------------------------------------===// #ifndef liblldb_ExecutionContext_h_ #define liblldb_ExecutionContext_h_ #include "lldb/lldb-private.h" #include "lldb/Target/StackID.h" #include "lldb/Host/Mutex.h" namespace lldb_private { //---------------------------------------------------------------------- /// @class ExecutionContextRef ExecutionContext.h "lldb/Target/ExecutionContext.h" /// @brief 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 instaces 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 objcts. /// 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 NULL. /// /// If \a exe_ctx_ptr is valid, then make weak references to any /// valid objects in the ExecutionContext, othewise 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); //------------------------------------------------------------------ /// Assignment operator /// /// Copy all weak refernces in \a rhs. //------------------------------------------------------------------ ExecutionContextRef & operator =(const ExecutionContextRef &rhs); //------------------------------------------------------------------ /// Assignment operator from a ExecutionContext /// /// Make weak refernces to any stringly referenced objects in \a exe_ctx. //------------------------------------------------------------------ ExecutionContextRef & operator =(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 refernces too the frame, thread, process and target. /// If the ExecutionContextScope object is valid and refers to a thread, /// make weak refernces too the thread, process and target. /// If the ExecutionContextScope object is valid and refers to a process, /// make weak refernces too the process and target. /// If the ExecutionContextScope object is valid and refers to a target, /// make weak refernces too the target. //------------------------------------------------------------------ ExecutionContextRef (ExecutionContextScope *exe_scope); //------------------------------------------------------------------ /// Construct using an execution context scope. /// /// If the ExecutionContextScope object refers to a frame, /// make weak refernces too the frame, thread, process and target. /// If the ExecutionContextScope object refers to a thread, /// make weak refernces too the thread, process and target. /// If the ExecutionContextScope object refers to a process, /// make weak refernces too the process and target. /// If the ExecutionContextScope object refers to a target, /// make weak refernces too the target. //------------------------------------------------------------------ ExecutionContextRef (ExecutionContextScope &exe_scope); ~ExecutionContextRef(); //------------------------------------------------------------------ /// Clear the object's state. /// /// Sets the process and thread to NULL, 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 wether this object has /// a weak reference and does not indicate wether the weak rerference /// 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 wether this object has /// a weak reference and does not indicate wether the weak rerference /// 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" /// @brief 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, Mutex::Locker &locker); ExecutionContext (const ExecutionContextRef *exe_ctx_ref, Mutex::Locker &locker); //------------------------------------------------------------------ // Create execution contexts from execution context scopes //------------------------------------------------------------------ ExecutionContext (ExecutionContextScope *exe_scope); ExecutionContext (ExecutionContextScope &exe_scope); ExecutionContext & operator =(const ExecutionContext &rhs); bool operator ==(const ExecutionContext &rhs) const; bool operator !=(const ExecutionContext &rhs) const; //------------------------------------------------------------------ /// 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 = NULL, StackFrame * frame = NULL); ~ExecutionContext(); //------------------------------------------------------------------ /// Clear the object's state. /// /// Sets the process and thread to NULL, 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 NULL. 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 NULL 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 NULL. 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 NULL 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 NULL. Calling HasThreadScope() or /// HasFrameScope() can help to pre-validate this pointer so that /// this accessor can freely be used without having to check for /// NULL 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 NULL. Calling HasFrameScope(), /// can help to pre-validate this pointer so that this accessor can /// freely be used without having to check for NULL 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 // liblldb_ExecutionContext_h_