summaryrefslogtreecommitdiffstats
path: root/lldb/include/lldb/Target/Thread.h
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/include/lldb/Target/Thread.h')
-rw-r--r--lldb/include/lldb/Target/Thread.h701
1 files changed, 701 insertions, 0 deletions
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
new file mode 100644
index 00000000000..cc5dcf89db0
--- /dev/null
+++ b/lldb/include/lldb/Target/Thread.h
@@ -0,0 +1,701 @@
+//===-- Thread.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Thread_h_
+#define liblldb_Thread_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Core/UserID.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/StackFrameList.h"
+
+#define LLDB_THREAD_MAX_STOP_EXC_DATA 8
+
+// I forward declare these here so I don't have to #include ThreadPlan, so in turn I
+// can use Thread.h in ThreadPlan.h.
+
+namespace lldb_private {
+
+class Thread :
+ public UserID,
+ public ExecutionContextScope
+{
+friend class ThreadPlan;
+public:
+ //----------------------------------------------------------------------
+ // StopInfo
+ //
+ // Describes the reason the thread it was created with stopped.
+ //----------------------------------------------------------------------
+ class StopInfo
+ {
+ public:
+ StopInfo(Thread *thread = NULL);
+
+ ~StopInfo();
+
+ // Clear clears the stop reason, but it does not clear the thread this
+ // StopInfo is tied to.
+ void
+ Clear();
+
+ lldb::StopReason
+ GetStopReason() const;
+
+ void
+ SetThread (Thread *thread);
+
+ Thread *
+ GetThread ();
+
+ void
+ SetStopReasonWithBreakpointSiteID (lldb::user_id_t break_id);
+
+ void
+ SetStopReasonWithWatchpointID (lldb::user_id_t watch_id);
+
+ void
+ SetStopReasonWithSignal (int signo);
+
+ void
+ SetStopReasonToTrace ();
+
+ void
+ SetStopReasonWithException (uint32_t exc_type, size_t exc_data_count);
+
+ void
+ SetStopReasonWithPlan (lldb::ThreadPlanSP &plan);
+
+ void
+ SetStopReasonToNone ();
+
+ const char *
+ GetStopDescription() const;
+
+ void
+ SetStopDescription(const char *desc);
+
+ lldb::user_id_t
+ GetBreakpointSiteID() const;
+
+ lldb::user_id_t
+ GetWatchpointID() const;
+
+ int
+ GetSignal() const;
+
+ lldb::user_id_t
+ GetPlanID () const;
+
+ uint32_t
+ GetExceptionType() const;
+
+ size_t
+ GetExceptionDataCount() const;
+
+ lldb::addr_t
+ GetExceptionDataAtIndex (uint32_t idx) const;
+
+ bool
+ SetExceptionDataAtIndex (uint32_t idx, lldb::addr_t data);
+
+ void
+ Dump (Stream *s) const;
+
+ protected:
+ lldb::StopReason m_reason;
+ //--------------------------------------------------------------
+ // For eStopReasonPlan the completed plan is stored in this shared pointer.
+ //--------------------------------------------------------------
+ lldb::ThreadPlanSP m_completed_plan_sp;
+ Thread *m_thread;
+ char m_description[256];
+ union
+ {
+ //--------------------------------------------------------------
+ // eStopReasonBreakpoint
+ //--------------------------------------------------------------
+ struct
+ {
+ lldb::user_id_t bp_site_id;
+ } breakpoint;
+ //--------------------------------------------------------------
+ // eStopReasonWatchpoint
+ //--------------------------------------------------------------
+ struct
+ {
+ lldb::user_id_t watch_id;
+ } watchpoint;
+ //--------------------------------------------------------------
+ // eStopReasonSignal
+ //--------------------------------------------------------------
+ struct
+ {
+ int signo;
+ } signal;
+ //--------------------------------------------------------------
+ // eStopReasonException
+ //--------------------------------------------------------------
+ struct
+ {
+ uint32_t type;
+ size_t data_count;
+ lldb::addr_t data[LLDB_THREAD_MAX_STOP_EXC_DATA];
+ } exception;
+ } m_details;
+ };
+
+ class RegisterCheckpoint
+ {
+ public:
+
+ RegisterCheckpoint() :
+ m_stack_id (),
+ m_data_sp ()
+ {
+ }
+
+ RegisterCheckpoint (const StackID &stack_id) :
+ m_stack_id (stack_id),
+ m_data_sp ()
+ {
+ }
+
+ ~RegisterCheckpoint()
+ {
+ }
+
+ const StackID &
+ GetStackID()
+ {
+ return m_stack_id;
+ }
+
+ void
+ SetStackID (const StackID &stack_id)
+ {
+ m_stack_id = stack_id;
+ }
+
+ lldb::DataBufferSP &
+ GetData()
+ {
+ return m_data_sp;
+ }
+
+ const lldb::DataBufferSP &
+ GetData() const
+ {
+ return m_data_sp;
+ }
+
+ protected:
+ StackID m_stack_id;
+ lldb::DataBufferSP m_data_sp;
+ };
+
+ Thread (Process &process, lldb::tid_t tid);
+ virtual ~Thread();
+
+ Process &
+ GetProcess() { return m_process; }
+
+ const Process &
+ GetProcess() const { return m_process; }
+
+ int
+ GetResumeSignal () const;
+
+ void
+ SetResumeSignal (int signal);
+
+ lldb::StateType
+ GetState() const;
+
+ lldb::ThreadSP
+ GetSP ();
+
+ void
+ SetState (lldb::StateType state);
+
+ lldb::StateType
+ GetResumeState () const;
+
+ void
+ SetResumeState (lldb::StateType state);
+
+ // This function is called on all the threads before "WillResume" in case
+ // a thread needs to change its state before the ThreadList polls all the
+ // threads to figure out which ones actually will get to run and how.
+ void
+ SetupForResume ();
+
+ // Override this to do platform specific tasks before resume, but always
+ // call the Thread::WillResume at the end of your work.
+
+ virtual bool
+ WillResume (lldb::StateType resume_state);
+
+ // This clears generic thread state after a resume. If you subclass this,
+ // be sure to call it.
+ virtual void
+ DidResume ();
+
+ virtual void
+ RefreshStateAfterStop() = 0;
+
+ void
+ WillStop ();
+
+ bool
+ ShouldStop (Event *event_ptr);
+
+ lldb::Vote
+ ShouldReportStop (Event *event_ptr);
+
+ lldb::Vote
+ ShouldReportRun (Event *event_ptr);
+
+ bool
+ GetStopInfo (StopInfo *stop_info);
+
+ bool
+ ThreadStoppedForAReason ();
+
+ virtual const char *
+ GetInfo () = 0;
+
+ virtual const char *
+ GetName ()
+ {
+ return NULL;
+ }
+
+ virtual const char *
+ GetQueueName ()
+ {
+ return NULL;
+ }
+
+ virtual uint32_t
+ GetStackFrameCount() = 0;
+
+ virtual lldb::StackFrameSP
+ GetStackFrameAtIndex (uint32_t idx) = 0;
+
+ lldb::StackFrameSP
+ GetCurrentFrame ();
+
+ uint32_t
+ SetCurrentFrame (lldb_private::StackFrame *frame);
+
+ void
+ SetCurrentFrameByIndex (uint32_t frame_idx);
+
+ virtual RegisterContext *
+ GetRegisterContext () = 0;
+
+ virtual bool
+ SaveFrameZeroState (RegisterCheckpoint &checkpoint) = 0;
+
+ virtual bool
+ RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint) = 0;
+
+ virtual RegisterContext *
+ CreateRegisterContextForFrame (StackFrame *frame) = 0;
+
+ virtual void
+ ClearStackFrames ()
+ {
+ m_frames.Clear();
+ }
+
+ void
+ DumpInfo (Stream &strm,
+ bool show_stop_reason,
+ bool show_name,
+ bool show_queue,
+ uint32_t frame_idx);// = UINT32_MAX);
+
+ //------------------------------------------------------------------
+ // Thread Plan Providers:
+ // This section provides the basic thread plans that the Process control
+ // machinery uses to run the target. ThreadPlan.h provides more details on
+ // how this mechanism works.
+ // The thread provides accessors to a set of plans that perform basic operations.
+ // The idea is that particular Platform plugins can override these methods to
+ // provide the implementation of these basic operations appropriate to their
+ // environment.
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Queues the base plan for a thread.
+ /// The version returned by Process does some things that are useful,
+ /// like handle breakpoints and signals, so if you return a plugin specific
+ /// one you probably want to call through to the Process one for anything
+ /// your plugin doesn't explicitly handle.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueFundamentalPlan (bool abort_other_plans);
+
+ //------------------------------------------------------------------
+ /// Queues the plan used to step over a breakpoint at the current PC of \a thread.
+ /// The default version returned by Process handles trap based breakpoints, and
+ /// will disable the breakpoint, single step over it, then re-enable it.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueThreadPlanForStepOverBreakpointPlan (bool abort_other_plans);
+
+ //------------------------------------------------------------------
+ /// Queues the plan used to step one instruction from the current PC of \a thread.
+ ///
+ /// @param[in] step_over
+ /// \b true if we step over calls to functions, false if we step in.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueThreadPlanForStepSingleInstruction (bool step_over,
+ bool abort_other_plans,
+ bool stop_other_threads);
+
+ //------------------------------------------------------------------
+ /// Queues the plan used to step through an address range, stepping into or over
+ /// function calls depending on the value of StepType.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] type
+ /// Type of step to do, only eStepTypeInto and eStepTypeOver are supported by this plan.
+ ///
+ /// @param[in] range
+ /// The address range to step through.
+ ///
+ /// @param[in] addr_context
+ /// When dealing with stepping through inlined functions the current PC is not enough information to know
+ /// what "step" means. For instance a series of nested inline functions might start at the same address.
+ // The \a addr_context provides the current symbol context the step
+ /// is supposed to be out of.
+ // FIXME: Currently unused.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueThreadPlanForStepRange (bool abort_other_plans,
+ lldb::StepType type,
+ const AddressRange &range,
+ const SymbolContext &addr_context,
+ lldb::RunMode stop_other_threads);
+
+ //------------------------------------------------------------------
+ /// Queue the plan used to step out of the function at the current PC of
+ /// \a thread.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] addr_context
+ /// When dealing with stepping through inlined functions the current PC is not enough information to know
+ /// what "step" means. For instance a series of nested inline functions might start at the same address.
+ // The \a addr_context provides the current symbol context the step
+ /// is supposed to be out of.
+ // FIXME: Currently unused.
+ ///
+ /// @param[in] first_insn
+ /// \b true if this is the first instruction of a function.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @param[in] stop_vote
+ /// @param[in] run_vote
+ /// See standard meanings for the stop & run votes in ThreadPlan.h.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueThreadPlanForStepOut (bool abort_other_plans,
+ SymbolContext *addr_context,
+ bool first_insn,
+ bool stop_other_threads,
+ lldb::Vote stop_vote = lldb::eVoteYes,
+ lldb::Vote run_vote = lldb::eVoteNoOpinion);
+
+ //------------------------------------------------------------------
+ /// Gets the plan used to step through the code that steps from a function
+ /// call site at the current PC into the actual function call.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueThreadPlanForStepThrough (bool abort_other_plans,
+ bool stop_other_threads);
+
+ //------------------------------------------------------------------
+ /// Gets the plan used to continue from the current PC.
+ /// This is a simple plan, mostly useful as a backstop when you are continuing
+ /// for some particular purpose.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @param[in] stop_vote
+ /// @param[in] run_vote
+ /// See standard meanings for the stop & run votes in ThreadPlan.h.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueThreadPlanForContinue (bool abort_other_plans,
+ bool stop_other_threads,
+ lldb::Vote stop_vote,
+ lldb::Vote run_vote = lldb::eVoteNoOpinion,
+ bool immediate = false);
+ //------------------------------------------------------------------
+ /// Gets the plan used to continue from the current PC.
+ /// This is a simple plan, mostly useful as a backstop when you are continuing
+ /// for some particular purpose.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @param[in] target_addr
+ /// The address to which we're running.
+ ///
+ /// @param[in] stop_other_threads
+ /// \b true if we will stop other threads while we single step this one.
+ ///
+ /// @return
+ /// A pointer to the newly queued thread plan, or NULL if the plan could not be queued.
+ //------------------------------------------------------------------
+ virtual ThreadPlan *
+ QueueThreadPlanForRunToAddress (bool abort_other_plans,
+ Address &target_addr,
+ bool stop_other_threads);
+
+ virtual ThreadPlan *
+ QueueThreadPlanForStepUntil (bool abort_other_plans,
+ lldb::addr_t *address_list,
+ size_t num_addresses,
+ bool stop_others);
+
+ virtual ThreadPlan *
+ QueueThreadPlanForCallFunction (bool abort_other_plans,
+ Address& function,
+ lldb::addr_t arg,
+ bool stop_other_threads,
+ bool discard_on_error = false);
+
+ virtual ThreadPlan *
+ QueueThreadPlanForCallFunction (bool abort_other_plans,
+ Address& function,
+ ValueList &args,
+ bool stop_other_threads,
+ bool discard_on_error = false);
+
+ //------------------------------------------------------------------
+ // Thread Plan accessors:
+ //------------------------------------------------------------------
+
+ //------------------------------------------------------------------
+ /// Gets the plan which will execute next on the plan stack.
+ ///
+ /// @return
+ /// A pointer to the next executed plan.
+ //------------------------------------------------------------------
+ ThreadPlan *
+ GetCurrentPlan ();
+
+ //------------------------------------------------------------------
+ /// Gets the inner-most plan that was popped off the plan stack in the
+ /// most recent stop. Useful for printing the stop reason accurately.
+ ///
+ /// @return
+ /// A pointer to the last completed plan.
+ //------------------------------------------------------------------
+ lldb::ThreadPlanSP
+ GetCompletedPlan ();
+
+ //------------------------------------------------------------------
+ /// Checks whether the given plan is in the completed plans for this
+ /// stop.
+ ///
+ /// @param[in] plan
+ /// Pointer to the plan you're checking.
+ ///
+ /// @return
+ /// Returns true if the input plan is in the completed plan stack,
+ /// false otherwise.
+ //------------------------------------------------------------------
+ bool
+ IsThreadPlanDone (ThreadPlan *plan);
+
+ //------------------------------------------------------------------
+ /// Checks whether the given plan is in the discarded plans for this
+ /// stop.
+ ///
+ /// @param[in] plan
+ /// Pointer to the plan you're checking.
+ ///
+ /// @return
+ /// Returns true if the input plan is in the discarded plan stack,
+ /// false otherwise.
+ //------------------------------------------------------------------
+ bool
+ WasThreadPlanDiscarded (ThreadPlan *plan);
+
+ //------------------------------------------------------------------
+ /// Queues a generic thread plan.
+ ///
+ /// @param[in] plan_sp
+ /// The plan to queue.
+ ///
+ /// @param[in] abort_other_plans
+ /// \b true if we discard the currently queued plans and replace them with this one.
+ /// Otherwise this plan will go on the end of the plan stack.
+ ///
+ /// @return
+ /// A pointer to the last completed plan.
+ //------------------------------------------------------------------
+ void
+ QueueThreadPlan (lldb::ThreadPlanSP &plan_sp, bool abort_other_plans);
+
+
+ //------------------------------------------------------------------
+ /// Discards the plans queued on the plan stack of the current thread. This is
+ /// arbitrated by the "Master" ThreadPlans, using the "OkayToDiscard" call.
+ // But if \a force is true, all thread plans are discarded.
+ //------------------------------------------------------------------
+ void
+ DiscardThreadPlans (bool force);
+
+ //------------------------------------------------------------------
+ /// Prints the current plan stack.
+ ///
+ /// @param[in] s
+ /// The stream to which to dump the plan stack info.
+ ///
+ //------------------------------------------------------------------
+ void
+ DumpThreadPlans (Stream *s) const;
+
+ // Get the thread index ID. The index ID that is guaranteed to not be
+ // re-used by a process. They start at 1 and increase with each new thread.
+ // This allows easy command line access by a unique ID that is easier to
+ // type than the actual system thread ID.
+ uint32_t
+ GetIndexID () const;
+
+ //------------------------------------------------------------------
+ // lldb::ExecutionContextScope pure virtual functions
+ //------------------------------------------------------------------
+ virtual Target *
+ CalculateTarget ();
+
+ virtual Process *
+ CalculateProcess ();
+
+ virtual Thread *
+ CalculateThread ();
+
+ virtual StackFrame *
+ CalculateStackFrame ();
+
+ virtual void
+ Calculate (ExecutionContext &exe_ctx);
+
+protected:
+ void
+ PushPlan (lldb::ThreadPlanSP &plan_sp);
+
+ void
+ PopPlan ();
+
+ void
+ DiscardPlan ();
+
+ ThreadPlan *GetPreviousPlan (ThreadPlan *plan);
+
+ virtual bool
+ GetRawStopReason (StopInfo *stop_info) = 0;
+
+ typedef std::vector<lldb::ThreadPlanSP> plan_stack;
+
+ //------------------------------------------------------------------
+ // Classes that inherit from Process can see and modify these
+ //------------------------------------------------------------------
+ Process & m_process; ///< The process that owns this thread.
+ const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread for easy UI/command line access.
+ lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this thread's current register state.
+ lldb::StateType m_state; ///< The state of our process.
+ plan_stack m_plan_stack; ///< The stack of plans this thread is executing.
+ plan_stack m_immediate_plan_stack; ///< The plans that need to get executed before any other work gets done.
+ plan_stack m_completed_plan_stack; ///< Plans that have been completed by this stop. They get deleted when the thread resumes.
+ plan_stack m_discarded_plan_stack; ///< Plans that have been discarded by this stop. They get deleted when the thread resumes.
+ mutable Mutex m_state_mutex; ///< Multithreaded protection for m_state.
+ StackFrameList m_frames; ///< The stack frames that get lazily populated after a thread stops.
+ uint32_t m_current_frame_idx;///< The current frame for this thread
+ int m_resume_signal; ///< The signal that should be used when continuing this thread.
+ lldb::StateType m_resume_state; ///< The state that indicates what this thread should do when the process is resumed.
+private:
+ //------------------------------------------------------------------
+ // For Thread only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN (Thread);
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_Thread_h_
OpenPOWER on IntegriCloud