| //===-- 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/Broadcaster.h" |
| #include "lldb/Core/Event.h" |
| #include "lldb/Core/StructuredData.h" |
| #include "lldb/Core/UserID.h" |
| #include "lldb/Core/UserSettingsController.h" |
| #include "lldb/Target/ExecutionContextScope.h" |
| #include "lldb/Target/RegisterCheckpoint.h" |
| #include "lldb/Target/StackFrameList.h" |
| |
| #define LLDB_THREAD_MAX_STOP_EXC_DATA 8 |
| |
| namespace lldb_private { |
| |
| class ThreadProperties : public Properties |
| { |
| public: |
| ThreadProperties(bool is_global); |
| |
| virtual |
| ~ThreadProperties(); |
| |
| //------------------------------------------------------------------ |
| /// The regular expression returned determines symbols that this |
| /// thread won't stop in during "step-in" operations. |
| /// |
| /// @return |
| /// A pointer to a regular expression to compare against symbols, |
| /// or NULL if all symbols are allowed. |
| /// |
| //------------------------------------------------------------------ |
| const RegularExpression * |
| GetSymbolsToAvoidRegexp(); |
| |
| FileSpecList & |
| GetLibrariesToAvoid() const; |
| |
| bool |
| GetTraceEnabledState() const; |
| |
| bool |
| GetStepInAvoidsNoDebug () const; |
| |
| bool |
| GetStepOutAvoidsNoDebug () const; |
| }; |
| |
| typedef std::shared_ptr<ThreadProperties> ThreadPropertiesSP; |
| |
| class Thread : |
| public std::enable_shared_from_this<Thread>, |
| public ThreadProperties, |
| public UserID, |
| public ExecutionContextScope, |
| public Broadcaster |
| { |
| public: |
| //------------------------------------------------------------------ |
| /// Broadcaster event bits definitions. |
| //------------------------------------------------------------------ |
| enum |
| { |
| eBroadcastBitStackChanged = (1 << 0), |
| eBroadcastBitThreadSuspended = (1 << 1), |
| eBroadcastBitThreadResumed = (1 << 2), |
| eBroadcastBitSelectedFrameChanged = (1 << 3), |
| eBroadcastBitThreadSelected = (1 << 4) |
| }; |
| |
| static ConstString &GetStaticBroadcasterClass (); |
| |
| virtual ConstString &GetBroadcasterClass() const |
| { |
| return GetStaticBroadcasterClass(); |
| } |
| |
| class ThreadEventData : |
| public EventData |
| { |
| public: |
| ThreadEventData (const lldb::ThreadSP thread_sp); |
| |
| ThreadEventData (const lldb::ThreadSP thread_sp, const StackID &stack_id); |
| |
| ThreadEventData(); |
| |
| virtual ~ThreadEventData(); |
| |
| static const ConstString & |
| GetFlavorString (); |
| |
| virtual const ConstString & |
| GetFlavor () const |
| { |
| return ThreadEventData::GetFlavorString (); |
| } |
| |
| virtual void |
| Dump (Stream *s) const; |
| |
| static const ThreadEventData * |
| GetEventDataFromEvent (const Event *event_ptr); |
| |
| static lldb::ThreadSP |
| GetThreadFromEvent (const Event *event_ptr); |
| |
| static StackID |
| GetStackIDFromEvent (const Event *event_ptr); |
| |
| static lldb::StackFrameSP |
| GetStackFrameFromEvent (const Event *event_ptr); |
| |
| lldb::ThreadSP |
| GetThread () const |
| { |
| return m_thread_sp; |
| } |
| |
| StackID |
| GetStackID () const |
| { |
| return m_stack_id; |
| } |
| |
| private: |
| lldb::ThreadSP m_thread_sp; |
| StackID m_stack_id; |
| DISALLOW_COPY_AND_ASSIGN (ThreadEventData); |
| }; |
| |
| |
| struct ThreadStateCheckpoint |
| { |
| uint32_t orig_stop_id; // Dunno if I need this yet but it is an interesting bit of data. |
| lldb::StopInfoSP stop_info_sp; // You have to restore the stop info or you might continue with the wrong signals. |
| lldb::RegisterCheckpointSP register_backup_sp; // You need to restore the registers, of course... |
| uint32_t current_inlined_depth; |
| lldb::addr_t current_inlined_pc; |
| }; |
| |
| static void |
| SettingsInitialize (); |
| |
| static void |
| SettingsTerminate (); |
| |
| static const ThreadPropertiesSP & |
| GetGlobalProperties(); |
| |
| //------------------------------------------------------------------ |
| /// Constructor |
| /// |
| /// @param [in] process |
| /// |
| /// @param [in] tid |
| /// |
| /// @param [in] use_invalid_index_id |
| /// Optional parameter, defaults to false. The only subclass that |
| /// is likely to set use_invalid_index_id == true is the HistoryThread |
| /// class. In that case, the Thread we are constructing represents |
| /// a thread from earlier in the program execution. We may have the |
| /// tid of the original thread that they represent but we don't want |
| /// to reuse the IndexID of that thread, or create a new one. If a |
| /// client wants to know the original thread's IndexID, they should use |
| /// Thread::GetExtendedBacktraceOriginatingIndexID(). |
| //------------------------------------------------------------------ |
| Thread (Process &process, lldb::tid_t tid, bool use_invalid_index_id = false); |
| |
| virtual ~Thread(); |
| |
| lldb::ProcessSP |
| GetProcess() const |
| { |
| return m_process_wp.lock(); |
| } |
| |
| int |
| GetResumeSignal () const |
| { |
| return m_resume_signal; |
| } |
| |
| void |
| SetResumeSignal (int signal) |
| { |
| m_resume_signal = signal; |
| } |
| |
| lldb::StateType |
| GetState() const; |
| |
| void |
| SetState (lldb::StateType state); |
| |
| lldb::StateType |
| GetResumeState () const |
| { |
| return m_resume_state; |
| } |
| |
| // This sets the "external resume state" of the thread. If the thread is suspended here, it should never |
| // get scheduled. Note that just because a thread is marked as "running" does not mean we will let it run in |
| // a given bit of process control. For instance "step" tries to stay on the selected thread it was issued on, |
| // which may involve suspending other threads temporarily. This temporary suspension is NOT reflected in the |
| // state set here and reported in GetResumeState. |
| // |
| // If you are just preparing all threads to run, you should not override the threads that are |
| // marked as suspended by the debugger. In that case, pass override_suspend = false. If you want |
| // to force the thread to run (e.g. the "thread continue" command, or are resetting the state |
| // (e.g. in SBThread::Resume()), then pass true to override_suspend. |
| void |
| SetResumeState (lldb::StateType state, bool override_suspend = false) |
| { |
| if (m_resume_state == lldb::eStateSuspended && !override_suspend) |
| return; |
| m_resume_state = state; |
| } |
| |
| // This function is called on all the threads before "ShouldResume" and |
| // "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 (); |
| |
| // Do not override this function, it is for thread plan logic only |
| bool |
| ShouldResume (lldb::StateType resume_state); |
| |
| // Override this to do platform specific tasks before resume. |
| virtual void |
| 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 (); |
| |
| // This notifies the thread when a private stop occurs. |
| virtual void |
| DidStop (); |
| |
| virtual void |
| RefreshStateAfterStop() = 0; |
| |
| void |
| WillStop (); |
| |
| bool |
| ShouldStop (Event *event_ptr); |
| |
| Vote |
| ShouldReportStop (Event *event_ptr); |
| |
| Vote |
| ShouldReportRun (Event *event_ptr); |
| |
| void |
| Flush (); |
| |
| // Return whether this thread matches the specification in ThreadSpec. This is a virtual |
| // method because at some point we may extend the thread spec with a platform specific |
| // dictionary of attributes, which then only the platform specific Thread implementation |
| // would know how to match. For now, this just calls through to the ThreadSpec's |
| // ThreadPassesBasicTests method. |
| virtual bool |
| MatchesSpec (const ThreadSpec *spec); |
| |
| lldb::StopInfoSP |
| GetStopInfo (); |
| |
| lldb::StopReason |
| GetStopReason(); |
| |
| // This sets the stop reason to a "blank" stop reason, so you can call functions on the thread |
| // without having the called function run with whatever stop reason you stopped with. |
| void |
| SetStopInfoToNothing(); |
| |
| bool |
| ThreadStoppedForAReason (); |
| |
| static const char * |
| RunModeAsCString (lldb::RunMode mode); |
| |
| static const char * |
| StopReasonAsCString (lldb::StopReason reason); |
| |
| virtual const char * |
| GetInfo () |
| { |
| return NULL; |
| } |
| |
| //------------------------------------------------------------------ |
| /// Retrieve a dictionary of information about this thread |
| /// |
| /// On Mac OS X systems there may be voucher information. |
| /// The top level dictionary returned will have an "activity" key and the |
| /// value of the activity is a dictionary. Keys in that dictionary will |
| /// be "name" and "id", among others. |
| /// There may also be "trace_messages" (an array) with each entry in that array |
| /// being a dictionary (keys include "message" with the text of the trace |
| /// message). |
| //------------------------------------------------------------------ |
| StructuredData::ObjectSP |
| GetExtendedInfo () |
| { |
| if (m_extended_info_fetched == false) |
| { |
| m_extended_info = FetchThreadExtendedInfo (); |
| m_extended_info_fetched = true; |
| } |
| return m_extended_info; |
| } |
| |
| virtual const char * |
| GetName () |
| { |
| return NULL; |
| } |
| |
| virtual void |
| SetName (const char *name) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| /// Retrieve the Queue ID for the queue currently using this Thread |
| /// |
| /// If this Thread is doing work on behalf of a libdispatch/GCD queue, |
| /// retrieve the QueueID. |
| /// |
| /// This is a unique identifier for the libdispatch/GCD queue in a |
| /// process. Often starting at 1 for the initial system-created |
| /// queues and incrementing, a QueueID will not be reused for a |
| /// different queue during the lifetime of a proces. |
| /// |
| /// @return |
| /// A QueueID if the Thread subclass implements this, else |
| /// LLDB_INVALID_QUEUE_ID. |
| //------------------------------------------------------------------ |
| virtual lldb::queue_id_t |
| GetQueueID () |
| { |
| return LLDB_INVALID_QUEUE_ID; |
| } |
| |
| virtual void |
| SetQueueID (lldb::queue_id_t new_val) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| /// Retrieve the Queue name for the queue currently using this Thread |
| /// |
| /// If this Thread is doing work on behalf of a libdispatch/GCD queue, |
| /// retrieve the Queue name. |
| /// |
| /// @return |
| /// The Queue name, if the Thread subclass implements this, else |
| /// NULL. |
| //------------------------------------------------------------------ |
| virtual const char * |
| GetQueueName () |
| { |
| return NULL; |
| } |
| |
| virtual void |
| SetQueueName (const char *name) |
| { |
| } |
| |
| //------------------------------------------------------------------ |
| /// Retrieve the Queue for this thread, if any. |
| /// |
| /// @return |
| /// A QueueSP for the queue that is currently associated with this |
| /// thread. |
| /// An empty shared pointer indicates that this thread is not |
| /// associated with a queue, or libdispatch queues are not |
| /// supported on this target. |
| //------------------------------------------------------------------ |
| virtual lldb::QueueSP |
| GetQueue () |
| { |
| return lldb::QueueSP(); |
| } |
| |
| //------------------------------------------------------------------ |
| /// Retrieve the address of the libdispatch_queue_t struct for queue |
| /// currently using this Thread |
| /// |
| /// If this Thread is doing work on behalf of a libdispatch/GCD queue, |
| /// retrieve the address of the libdispatch_queue_t structure describing |
| /// the queue. |
| /// |
| /// This address may be reused for different queues later in the Process |
| /// lifetime and should not be used to identify a queue uniquely. Use |
| /// the GetQueueID() call for that. |
| /// |
| /// @return |
| /// The Queue's libdispatch_queue_t address if the Thread subclass |
| /// implements this, else LLDB_INVALID_ADDRESS. |
| //------------------------------------------------------------------ |
| virtual lldb::addr_t |
| GetQueueLibdispatchQueueAddress () |
| { |
| return LLDB_INVALID_ADDRESS; |
| } |
| |
| virtual uint32_t |
| GetStackFrameCount() |
| { |
| return GetStackFrameList()->GetNumFrames(); |
| } |
| |
| virtual lldb::StackFrameSP |
| GetStackFrameAtIndex (uint32_t idx) |
| { |
| return GetStackFrameList()->GetFrameAtIndex(idx); |
| } |
| |
| virtual lldb::StackFrameSP |
| GetFrameWithConcreteFrameIndex (uint32_t unwind_idx); |
| |
| bool |
| DecrementCurrentInlinedDepth() |
| { |
| return GetStackFrameList()->DecrementCurrentInlinedDepth(); |
| } |
| |
| uint32_t |
| GetCurrentInlinedDepth() |
| { |
| return GetStackFrameList()->GetCurrentInlinedDepth(); |
| } |
| |
| Error |
| ReturnFromFrameWithIndex (uint32_t frame_idx, lldb::ValueObjectSP return_value_sp, bool broadcast = false); |
| |
| Error |
| ReturnFromFrame (lldb::StackFrameSP frame_sp, lldb::ValueObjectSP return_value_sp, bool broadcast = false); |
| |
| Error |
| JumpToLine (const FileSpec &file, uint32_t line, bool can_leave_function, std::string *warnings = NULL); |
| |
| virtual lldb::StackFrameSP |
| GetFrameWithStackID (const StackID &stack_id) |
| { |
| if (stack_id.IsValid()) |
| return GetStackFrameList()->GetFrameWithStackID (stack_id); |
| return lldb::StackFrameSP(); |
| } |
| |
| uint32_t |
| GetSelectedFrameIndex () |
| { |
| return GetStackFrameList()->GetSelectedFrameIndex(); |
| } |
| |
| lldb::StackFrameSP |
| GetSelectedFrame () |
| { |
| lldb::StackFrameListSP stack_frame_list_sp(GetStackFrameList()); |
| return stack_frame_list_sp->GetFrameAtIndex (stack_frame_list_sp->GetSelectedFrameIndex()); |
| } |
| |
| uint32_t |
| SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast = false); |
| |
| |
| bool |
| SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast = false); |
| |
| bool |
| SetSelectedFrameByIndexNoisily (uint32_t frame_idx, Stream &output_stream); |
| |
| void |
| SetDefaultFileAndLineToSelectedFrame() |
| { |
| GetStackFrameList()->SetDefaultFileAndLineToSelectedFrame(); |
| } |
| |
| virtual lldb::RegisterContextSP |
| GetRegisterContext () = 0; |
| |
| virtual lldb::RegisterContextSP |
| CreateRegisterContextForFrame (StackFrame *frame) = 0; |
| |
| virtual void |
| ClearStackFrames (); |
| |
| virtual bool |
| SetBackingThread (const lldb::ThreadSP &thread_sp) |
| { |
| return false; |
| } |
| |
| virtual lldb::ThreadSP |
| GetBackingThread () const |
| { |
| return lldb::ThreadSP(); |
| } |
| |
| virtual void |
| ClearBackingThread () |
| { |
| // Subclasses can use this function if a thread is actually backed by |
| // another thread. This is currently used for the OperatingSystem plug-ins |
| // where they might have a thread that is in memory, yet its registers |
| // are available through the lldb_private::Thread subclass for the current |
| // lldb_private::Process class. Since each time the process stops the backing |
| // threads for memory threads can change, we need a way to clear the backing |
| // thread for all memory threads each time we stop. |
| } |
| |
| void |
| DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx); |
| |
| bool |
| GetDescription (Stream &s, lldb::DescriptionLevel level, bool json_output); |
| |
| //------------------------------------------------------------------ |
| /// Default implementation for stepping into. |
| /// |
| /// This function is designed to be used by commands where the |
| /// process is publicly stopped. |
| /// |
| /// @param[in] source_step |
| /// If true and the frame has debug info, then do a source level |
| /// step in, else do a single instruction step in. |
| /// |
| /// @param[in] step_in_avoids_code_without_debug_info |
| /// If \a true, then avoid stepping into code that doesn't have |
| /// debug info, else step into any code regardless of whether it |
| /// has debug info. |
| /// |
| /// @param[in] step_out_avoids_code_without_debug_info |
| /// If \a true, then if you step out to code with no debug info, keep |
| /// stepping out till you get to code with debug info. |
| /// |
| /// @return |
| /// An error that describes anything that went wrong |
| //------------------------------------------------------------------ |
| virtual Error |
| StepIn (bool source_step, |
| LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate, |
| LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); |
| |
| //------------------------------------------------------------------ |
| /// Default implementation for stepping over. |
| /// |
| /// This function is designed to be used by commands where the |
| /// process is publicly stopped. |
| /// |
| /// @param[in] source_step |
| /// If true and the frame has debug info, then do a source level |
| /// step over, else do a single instruction step over. |
| /// |
| /// @return |
| /// An error that describes anything that went wrong |
| //------------------------------------------------------------------ |
| virtual Error |
| StepOver (bool source_step, |
| LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); |
| |
| //------------------------------------------------------------------ |
| /// Default implementation for stepping out. |
| /// |
| /// This function is designed to be used by commands where the |
| /// process is publicly stopped. |
| /// |
| /// @return |
| /// An error that describes anything that went wrong |
| //------------------------------------------------------------------ |
| virtual Error |
| StepOut (); |
| //------------------------------------------------------------------ |
| /// Retrieves the per-thread data area. |
| /// Most OSs maintain a per-thread pointer (e.g. the FS register on |
| /// x64), which we return the value of here. |
| /// |
| /// @return |
| /// LLDB_INVALID_ADDRESS if not supported, otherwise the thread |
| /// pointer value. |
| //------------------------------------------------------------------ |
| virtual lldb::addr_t |
| GetThreadPointer (); |
| |
| //------------------------------------------------------------------ |
| /// Retrieves the per-module TLS block for a thread. |
| /// |
| /// @param[in] module |
| /// The module to query TLS data for. |
| /// |
| /// @return |
| /// If the thread has TLS data allocated for the |
| /// module, the address of the TLS block. Otherwise |
| /// LLDB_INVALID_ADDRESS is returned. |
| //------------------------------------------------------------------ |
| virtual lldb::addr_t |
| GetThreadLocalData (const lldb::ModuleSP module); |
| |
| //------------------------------------------------------------------ |
| /// Check whether this thread is safe to run functions |
| /// |
| /// The SystemRuntime may know of certain thread states (functions in |
| /// process of execution, for instance) which can make it unsafe for |
| /// functions to be called. |
| /// |
| /// @return |
| /// True if it is safe to call functions on this thread. |
| /// False if function calls should be avoided on this thread. |
| //------------------------------------------------------------------ |
| virtual bool |
| SafeToCallFunctions (); |
| |
| //------------------------------------------------------------------ |
| // 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. |
| // |
| // NB: All the QueueThreadPlanXXX providers return Shared Pointers to |
| // Thread plans. This is useful so that you can modify the plans after |
| // creation in ways specific to that plan type. Also, it is often necessary for |
| // ThreadPlans that utilize other ThreadPlans to implement their task to keep a shared |
| // pointer to the sub-plan. |
| // But besides that, the shared pointers should only be held onto by entities who live no longer |
| // than the thread containing the ThreadPlan. |
| // FIXME: If this becomes a problem, we can make a version that just returns a pointer, |
| // which it is clearly unsafe to hold onto, and a shared pointer version, and only allow |
| // ThreadPlan and Co. to use the latter. That is made more annoying to do because there's |
| // no elegant way to friend a method to all sub-classes of a given class. |
| // |
| //------------------------------------------------------------------ |
| |
| //------------------------------------------------------------------ |
| /// 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 shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. |
| //------------------------------------------------------------------ |
| virtual lldb::ThreadPlanSP |
| QueueFundamentalPlan (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 shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. |
| //------------------------------------------------------------------ |
| virtual lldb::ThreadPlanSP |
| QueueThreadPlanForStepSingleInstruction (bool step_over, |
| bool abort_other_plans, |
| bool stop_other_threads); |
| |
| //------------------------------------------------------------------ |
| /// Queues the plan used to step through an address range, stepping over |
| /// function calls. |
| /// |
| /// @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. |
| /// |
| /// @param[in] step_out_avoids_code_without_debug_info |
| /// If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info. |
| /// If eLazyBoolCalculate, we will consult the default set in the thread. |
| /// |
| /// @return |
| /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. |
| //------------------------------------------------------------------ |
| virtual lldb::ThreadPlanSP |
| QueueThreadPlanForStepOverRange (bool abort_other_plans, |
| const AddressRange &range, |
| const SymbolContext &addr_context, |
| lldb::RunMode stop_other_threads, |
| LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); |
| |
| //------------------------------------------------------------------ |
| /// Queues the plan used to step through an address range, stepping into functions. |
| /// |
| /// @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] step_in_target |
| /// Name if function we are trying to step into. We will step out if we don't land in that function. |
| /// |
| /// @param[in] stop_other_threads |
| /// \b true if we will stop other threads while we single step this one. |
| /// |
| /// @param[in] step_in_avoids_code_without_debug_info |
| /// If eLazyBoolYes we will step out if we step into code with no debug info. |
| /// If eLazyBoolCalculate we will consult the default set in the thread. |
| /// |
| /// @param[in] step_out_avoids_code_without_debug_info |
| /// If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info. |
| /// If eLazyBoolCalculate, it will consult the default set in the thread. |
| /// |
| /// @return |
| /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. |
| //------------------------------------------------------------------ |
| virtual lldb::ThreadPlanSP |
| QueueThreadPlanForStepInRange (bool abort_other_plans, |
| const AddressRange &range, |
| const SymbolContext &addr_context, |
| const char *step_in_target, |
| lldb::RunMode stop_other_threads, |
| LazyBool step_in_avoids_code_without_debug_info = eLazyBoolCalculate, |
| LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); |
| |
| //------------------------------------------------------------------ |
| /// 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. |
| /// |
| /// @param[in] step_out_avoids_code_without_debug_info |
| /// If eLazyBoolYes, if the step over steps out it will continue to step out till it comes to a frame with debug info. |
| /// If eLazyBoolCalculate, it will consult the default set in the thread. |
| /// |
| /// @return |
| /// A shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. |
| //------------------------------------------------------------------ |
| virtual lldb::ThreadPlanSP |
| QueueThreadPlanForStepOut (bool abort_other_plans, |
| SymbolContext *addr_context, |
| bool first_insn, |
| bool stop_other_threads, |
| Vote stop_vote, // = eVoteYes, |
| Vote run_vote, // = eVoteNoOpinion); |
| uint32_t frame_idx, |
| LazyBool step_out_avoids_code_without_debug_info = eLazyBoolCalculate); |
| |
| //------------------------------------------------------------------ |
| /// Queue the plan used to step out of the function at the current PC of |
| /// a thread. This version does not consult the should stop here callback, and should only |
| /// be used by other thread plans when they need to retain control of the step out. |
| /// |
| /// @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 shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. |
| //------------------------------------------------------------------ |
| virtual lldb::ThreadPlanSP |
| QueueThreadPlanForStepOutNoShouldStop (bool abort_other_plans, |
| SymbolContext *addr_context, |
| bool first_insn, |
| bool stop_other_threads, |
| Vote stop_vote, // = eVoteYes, |
| Vote run_vote, // = eVoteNoOpinion); |
| uint32_t frame_idx); |
| |
| //------------------------------------------------------------------ |
| /// 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] return_stack_id |
| /// The stack id that we will return to (by setting backstop breakpoints on the return |
| /// address to that frame) if we fail to step through. |
| /// |
| /// @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 shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. |
| //------------------------------------------------------------------ |
| virtual lldb::ThreadPlanSP |
| QueueThreadPlanForStepThrough (StackID &return_stack_id, |
| 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] 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 shared pointer to the newly queued thread plan, or NULL if the plan could not be queued. |
| //------------------------------------------------------------------ |
| virtual lldb::ThreadPlanSP |
| QueueThreadPlanForRunToAddress (bool abort_other_plans, |
| Address &target_addr, |
| bool stop_other_threads); |
| |
| virtual lldb::ThreadPlanSP |
| QueueThreadPlanForStepUntil (bool abort_other_plans, |
| lldb::addr_t *address_list, |
| size_t num_addresses, |
| bool stop_others, |
| uint32_t frame_idx); |
| |
| //------------------------------------------------------------------ |
| // Thread Plan accessors: |
| //------------------------------------------------------------------ |
| |
| //------------------------------------------------------------------ |
| /// Gets the plan which will execute next on the plan stack. |
| /// |
| /// @return |
| /// A pointer to the next executed plan. |
| //------------------------------------------------------------------ |
| ThreadPlan * |
| GetCurrentPlan (); |
| |
| //------------------------------------------------------------------ |
| /// Unwinds the thread stack for the innermost expression plan currently |
| /// on the thread plan stack. |
| /// |
| /// @return |
| /// An error if the thread plan could not be unwound. |
| //------------------------------------------------------------------ |
| |
| Error |
| UnwindInnermostExpression(); |
| |
| private: |
| bool |
| PlanIsBasePlan (ThreadPlan *plan_ptr); |
| |
| void |
| BroadcastSelectedFrameChange(StackID &new_frame_id); |
| |
| public: |
| |
| //------------------------------------------------------------------ |
| /// Gets the outer-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 (); |
| |
| //------------------------------------------------------------------ |
| /// Gets the outer-most return value from the completed plans |
| /// |
| /// @return |
| /// A ValueObjectSP, either empty if there is no return value, |
| /// or containing the return value. |
| //------------------------------------------------------------------ |
| lldb::ValueObjectSP |
| GetReturnValueObject (); |
| |
| //------------------------------------------------------------------ |
| /// Gets the outer-most expression variable from the completed plans |
| /// |
| /// @return |
| /// A ClangExpressionVariableSP, either empty if there is no |
| /// plan completed an expression during the current stop |
| /// or the expression variable that was made for the completed expression. |
| //------------------------------------------------------------------ |
| lldb::ClangExpressionVariableSP |
| GetExpressionVariable (); |
| |
| //------------------------------------------------------------------ |
| /// 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); |
| |
| //------------------------------------------------------------------ |
| /// Discards the plans queued on the plan stack of the current thread up to and |
| /// including up_to_plan_sp. |
| // |
| // @param[in] up_to_plan_sp |
| // Discard all plans up to and including this one. |
| //------------------------------------------------------------------ |
| void |
| DiscardThreadPlansUpToPlan (lldb::ThreadPlanSP &up_to_plan_sp); |
| |
| void |
| DiscardThreadPlansUpToPlan (ThreadPlan *up_to_plan_ptr); |
| |
| //------------------------------------------------------------------ |
| /// Prints the current plan stack. |
| /// |
| /// @param[in] s |
| /// The stream to which to dump the plan stack info. |
| /// |
| //------------------------------------------------------------------ |
| void |
| DumpThreadPlans (Stream *s) const; |
| |
| virtual bool |
| CheckpointThreadState (ThreadStateCheckpoint &saved_state); |
| |
| virtual bool |
| RestoreRegisterStateFromCheckpoint (ThreadStateCheckpoint &saved_state); |
| |
| virtual bool |
| RestoreThreadStateFromCheckpoint (ThreadStateCheckpoint &saved_state); |
| |
| void |
| EnableTracer (bool value, bool single_step); |
| |
| void |
| SetTracer (lldb::ThreadPlanTracerSP &tracer_sp); |
| |
| //------------------------------------------------------------------ |
| // 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; |
| |
| //------------------------------------------------------------------ |
| // Get the originating thread's index ID. |
| // In the case of an "extended" thread -- a thread which represents |
| // the stack that enqueued/spawned work that is currently executing -- |
| // we need to provide the IndexID of the thread that actually did |
| // this work. We don't want to just masquerade as that thread's IndexID |
| // by using it in our own IndexID because that way leads to madness - |
| // but the driver program which is iterating over extended threads |
| // may ask for the OriginatingThreadID to display that information |
| // to the user. |
| // Normal threads will return the same thing as GetIndexID(); |
| //------------------------------------------------------------------ |
| virtual uint32_t |
| GetExtendedBacktraceOriginatingIndexID () |
| { |
| return GetIndexID (); |
| } |
| |
| //------------------------------------------------------------------ |
| // The API ID is often the same as the Thread::GetID(), but not in |
| // all cases. Thread::GetID() is the user visible thread ID that |
| // clients would want to see. The API thread ID is the thread ID |
| // that is used when sending data to/from the debugging protocol. |
| //------------------------------------------------------------------ |
| virtual lldb::user_id_t |
| GetProtocolID () const |
| { |
| return GetID(); |
| } |
| |
| //------------------------------------------------------------------ |
| // lldb::ExecutionContextScope pure virtual functions |
| //------------------------------------------------------------------ |
| virtual lldb::TargetSP |
| CalculateTarget (); |
| |
| virtual lldb::ProcessSP |
| CalculateProcess (); |
| |
| virtual lldb::ThreadSP |
| CalculateThread (); |
| |
| virtual lldb::StackFrameSP |
| CalculateStackFrame (); |
| |
| virtual void |
| CalculateExecutionContext (ExecutionContext &exe_ctx); |
| |
| lldb::StackFrameSP |
| GetStackFrameSPForStackFramePtr (StackFrame *stack_frame_ptr); |
| |
| size_t |
| GetStatus (Stream &strm, |
| uint32_t start_frame, |
| uint32_t num_frames, |
| uint32_t num_frames_with_source); |
| |
| size_t |
| GetStackFrameStatus (Stream& strm, |
| uint32_t first_frame, |
| uint32_t num_frames, |
| bool show_frame_info, |
| uint32_t num_frames_with_source); |
| |
| // We need a way to verify that even though we have a thread in a shared |
| // pointer that the object itself is still valid. Currently this won't be |
| // the case if DestroyThread() was called. DestroyThread is called when |
| // a thread has been removed from the Process' thread list. |
| bool |
| IsValid () const |
| { |
| return !m_destroy_called; |
| } |
| |
| // Sets and returns a valid stop info based on the process stop ID and the |
| // current thread plan. If the thread stop ID does not match the process' |
| // stop ID, the private stop reason is not set and an invalid StopInfoSP may |
| // be returned. |
| // |
| // NOTE: This function must be called before the current thread plan is |
| // moved to the completed plan stack (in Thread::ShouldStop()). |
| // |
| // NOTE: If subclasses override this function, ensure they do not overwrite |
| // the m_actual_stop_info if it is valid. The stop info may be a |
| // "checkpointed and restored" stop info, so if it is still around it is |
| // right even if you have not calculated this yourself, or if it disagrees |
| // with what you might have calculated. |
| virtual lldb::StopInfoSP |
| GetPrivateStopInfo (); |
| |
| //---------------------------------------------------------------------- |
| // Ask the thread subclass to set its stop info. |
| // |
| // Thread subclasses should call Thread::SetStopInfo(...) with the |
| // reason the thread stopped. |
| // |
| // @return |
| // True if Thread::SetStopInfo(...) was called, false otherwise. |
| //---------------------------------------------------------------------- |
| virtual bool |
| CalculateStopInfo () = 0; |
| |
| //---------------------------------------------------------------------- |
| // Gets the temporary resume state for a thread. |
| // |
| // This value gets set in each thread by complex debugger logic in |
| // Thread::ShouldResume() and an appropriate thread resume state will get |
| // set in each thread every time the process is resumed prior to calling |
| // Process::DoResume(). The lldb_private::Process subclass should adhere |
| // to the thread resume state request which will be one of: |
| // |
| // eStateRunning - thread will resume when process is resumed |
| // eStateStepping - thread should step 1 instruction and stop when process |
| // is resumed |
| // eStateSuspended - thread should not execute any instructions when |
| // process is resumed |
| //---------------------------------------------------------------------- |
| lldb::StateType |
| GetTemporaryResumeState() const |
| { |
| return m_temporary_resume_state; |
| } |
| |
| void |
| SetStopInfo (const lldb::StopInfoSP &stop_info_sp); |
| |
| void |
| SetShouldReportStop (Vote vote); |
| |
| //---------------------------------------------------------------------- |
| /// Sets the extended backtrace token for this thread |
| /// |
| /// Some Thread subclasses may maintain a token to help with providing |
| /// an extended backtrace. The SystemRuntime plugin will set/request this. |
| /// |
| /// @param [in] token |
| //---------------------------------------------------------------------- |
| virtual void |
| SetExtendedBacktraceToken (uint64_t token) { } |
| |
| //---------------------------------------------------------------------- |
| /// Gets the extended backtrace token for this thread |
| /// |
| /// Some Thread subclasses may maintain a token to help with providing |
| /// an extended backtrace. The SystemRuntime plugin will set/request this. |
| /// |
| /// @return |
| /// The token needed by the SystemRuntime to create an extended backtrace. |
| /// LLDB_INVALID_ADDRESS is returned if no token is available. |
| //---------------------------------------------------------------------- |
| virtual uint64_t |
| GetExtendedBacktraceToken () |
| { |
| return LLDB_INVALID_ADDRESS; |
| } |
| |
| protected: |
| |
| friend class ThreadPlan; |
| friend class ThreadList; |
| friend class ThreadEventData; |
| friend class StackFrameList; |
| friend class StackFrame; |
| friend class OperatingSystem; |
| |
| // This is necessary to make sure thread assets get destroyed while the thread is still in good shape |
| // to call virtual thread methods. This must be called by classes that derive from Thread in their destructor. |
| virtual void DestroyThread (); |
| |
| void |
| PushPlan (lldb::ThreadPlanSP &plan_sp); |
| |
| void |
| PopPlan (); |
| |
| void |
| DiscardPlan (); |
| |
| ThreadPlan *GetPreviousPlan (ThreadPlan *plan); |
| |
| typedef std::vector<lldb::ThreadPlanSP> plan_stack; |
| |
| virtual lldb_private::Unwind * |
| GetUnwinder (); |
| |
| // Check to see whether the thread is still at the last breakpoint hit that stopped it. |
| virtual bool |
| IsStillAtLastBreakpointHit(); |
| |
| // Some threads are threads that are made up by OperatingSystem plugins that |
| // are threads that exist and are context switched out into memory. The |
| // OperatingSystem plug-in need a ways to know if a thread is "real" or made |
| // up. |
| virtual bool |
| IsOperatingSystemPluginThread () const |
| { |
| return false; |
| } |
| |
| // Subclasses that have a way to get an extended info dictionary for this thread should |
| // fill |
| virtual lldb_private::StructuredData::ObjectSP |
| FetchThreadExtendedInfo () |
| { |
| return StructuredData::ObjectSP(); |
| } |
| |
| lldb::StackFrameListSP |
| GetStackFrameList (); |
| |
| |
| //------------------------------------------------------------------ |
| // Classes that inherit from Process can see and modify these |
| //------------------------------------------------------------------ |
| lldb::ProcessWP m_process_wp; ///< The process that owns this thread. |
| lldb::StopInfoSP m_stop_info_sp; ///< The private stop reason for this thread |
| uint32_t m_stop_info_stop_id; // This is the stop id for which the StopInfo is valid. Can use this so you know that |
| // the thread's m_stop_info_sp is current and you don't have to fetch it again |
| 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. |
| mutable Mutex m_state_mutex; ///< Multithreaded protection for m_state. |
| plan_stack m_plan_stack; ///< The stack of plans this thread is executing. |
| 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_frame_mutex; ///< Multithreaded protection for m_state. |
| 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 the last time this thread stopped. |
| int m_resume_signal; ///< The signal that should be used when continuing this thread. |
| lldb::StateType m_resume_state; ///< This state is used to force a thread to be suspended from outside the ThreadPlan logic. |
| lldb::StateType m_temporary_resume_state; ///< This state records what the thread was told to do by the thread plan logic for the current resume. |
| /// It gets set in Thread::ShouldResume. |
| std::unique_ptr<lldb_private::Unwind> m_unwinder_ap; |
| bool m_destroy_called; // This is used internally to make sure derived Thread classes call DestroyThread. |
| LazyBool m_override_should_notify; |
| private: |
| bool m_extended_info_fetched; // Have we tried to retrieve the m_extended_info for this thread? |
| StructuredData::ObjectSP m_extended_info; // The extended info for this thread |
| //------------------------------------------------------------------ |
| // For Thread only |
| //------------------------------------------------------------------ |
| |
| DISALLOW_COPY_AND_ASSIGN (Thread); |
| |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // liblldb_Thread_h_ |