diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:26:05 +0000 |
commit | 14f1b3e8826ce43b978db93a62d1166055db5394 (patch) | |
tree | 0a00ad8d3498783fe0193f3b656bca17c4c8697d /include/lldb/Target/Thread.h | |
parent | 4ee8c119c71a06dcad1e0fecc8c675e480e59337 (diff) | |
download | src-14f1b3e8826ce43b978db93a62d1166055db5394.tar.gz src-14f1b3e8826ce43b978db93a62d1166055db5394.zip |
Vendor import of lldb trunk r290819:vendor/lldb/lldb-trunk-r290819
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=311128
svn path=/vendor/lldb/lldb-trunk-r290819/; revision=311129; tag=vendor/lldb/lldb-trunk-r290819
Diffstat (limited to 'include/lldb/Target/Thread.h')
-rw-r--r-- | include/lldb/Target/Thread.h | 2701 |
1 files changed, 1286 insertions, 1415 deletions
diff --git a/include/lldb/Target/Thread.h b/include/lldb/Target/Thread.h index f3cf97325e16..63449bbf930e 100644 --- a/include/lldb/Target/Thread.h +++ b/include/lldb/Target/Thread.h @@ -19,7 +19,6 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Event.h" #include "lldb/Core/StructuredData.h" @@ -28,1452 +27,1324 @@ #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/RegisterCheckpoint.h" #include "lldb/Target/StackFrameList.h" +#include "lldb/lldb-private.h" #define LLDB_THREAD_MAX_STOP_EXC_DATA 8 namespace lldb_private { -class ThreadProperties : public Properties -{ +class ThreadProperties : public Properties { public: - ThreadProperties(bool is_global); - - ~ThreadProperties() override; - - //------------------------------------------------------------------ - /// 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 nullptr 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 (); - - ConstString &GetBroadcasterClass() const override - { - return GetStaticBroadcasterClass(); - } - - class ThreadEventData : - public EventData - { - public: - ThreadEventData (const lldb::ThreadSP thread_sp); - - ThreadEventData (const lldb::ThreadSP thread_sp, const StackID &stack_id); - - ThreadEventData(); - - ~ThreadEventData() override; - - static const ConstString & - GetFlavorString (); - - const ConstString & - GetFlavor() const override - { - return ThreadEventData::GetFlavorString (); - } - - void - Dump(Stream *s) const override; - - 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; - }; - - //------------------------------------------------------------------ - /// 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); - - ~Thread() override; - - static void - SettingsInitialize (); - - static void - SettingsTerminate (); - - static const ThreadPropertiesSP & - GetGlobalProperties(); - - 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); - - //------------------------------------------------------------------ - /// Sets the USER resume state for this thread. If you set a thread to suspended with - /// this API, it won't take part in any of the arbitration for ShouldResume, and will stay - /// suspended even when other threads do get to run. - /// - /// N.B. This is not the state that is used internally by thread plans to implement - /// staying on one thread while stepping over a breakpoint, etc. The is the - /// TemporaryResume state, and if you are implementing some bit of strategy in the stepping - /// machinery you should be using that state and not the user resume state. - /// - /// 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. - /// @return - /// The User resume state for this thread. - //------------------------------------------------------------------ - void - SetResumeState (lldb::StateType state, bool override_suspend = false) - { - if (m_resume_state == lldb::eStateSuspended && !override_suspend) - return; - m_resume_state = state; - } - - //------------------------------------------------------------------ - /// Gets the USER resume state for this thread. This is not the same as what - /// this thread is going to do for any particular step, however if this thread - /// returns eStateSuspended, then the process control logic will never allow this - /// thread to run. - /// - /// @return - /// The User resume state for this thread. - //------------------------------------------------------------------ - lldb::StateType - GetResumeState () const - { - return m_resume_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(); - - bool - StopInfoIsUpToDate() const; - - // 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 nullptr; - } - - //------------------------------------------------------------------ - /// 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 nullptr; - } - - virtual void - SetName (const char *name) - { - } - - //------------------------------------------------------------------ - /// Whether this thread can be associated with a libdispatch queue - /// - /// The Thread may know if it is associated with a libdispatch queue, - /// it may know definitively that it is NOT associated with a libdispatch - /// queue, or it may be unknown whether it is associated with a libdispatch - /// queue. - /// - /// @return - /// eLazyBoolNo if this thread is definitely not associated with a - /// libdispatch queue (e.g. on a non-Darwin system where GCD aka - /// libdispatch is not available). - /// - /// eLazyBoolYes this thread is associated with a libdispatch queue. - /// - /// eLazyBoolCalculate this thread may be associated with a libdispatch - /// queue but the thread doesn't know one way or the other. - //------------------------------------------------------------------ - virtual lldb_private::LazyBool - GetAssociatedWithLibdispatchQueue () - { - return eLazyBoolNo; - } - - virtual void - SetAssociatedWithLibdispatchQueue (lldb_private::LazyBool associated_with_libdispatch_queue) - { - } - - //------------------------------------------------------------------ - /// 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 - /// nullptr. - //------------------------------------------------------------------ - virtual const char * - GetQueueName () - { - return nullptr; - } + ThreadProperties(bool is_global); - virtual void - SetQueueName (const char *name) - { - } - - //------------------------------------------------------------------ - /// Retrieve the Queue kind for the queue currently using this Thread - /// - /// If this Thread is doing work on behalf of a libdispatch/GCD queue, - /// retrieve the Queue kind - either eQueueKindSerial or - /// eQueueKindConcurrent, indicating that this queue processes work - /// items serially or concurrently. - /// - /// @return - /// The Queue kind, if the Thread subclass implements this, else - /// eQueueKindUnknown. - //------------------------------------------------------------------ - virtual lldb::QueueKind - GetQueueKind () - { - return lldb::eQueueKindUnknown; - } - - virtual void - SetQueueKind (lldb::QueueKind kind) - { - } - - //------------------------------------------------------------------ - /// 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; - } + ~ThreadProperties() override; - virtual void - SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t) - { - } - - //------------------------------------------------------------------ - /// Whether this Thread already has all the Queue information cached or not - /// - /// A Thread may be associated with a libdispatch work Queue at a given - /// public stop event. If so, the thread can satisify requests like - /// GetQueueLibdispatchQueueAddress, GetQueueKind, GetQueueName, and GetQueueID - /// either from information from the remote debug stub when it is initially - /// created, or it can query the SystemRuntime for that information. - /// - /// This method allows the SystemRuntime to discover if a thread has this - /// information already, instead of calling the thread to get the information - /// and having the thread call the SystemRuntime again. - //------------------------------------------------------------------ - virtual bool - ThreadHasQueueInformation () const - { - return false; - } - - 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 = nullptr); - - virtual lldb::StackFrameSP - GetFrameWithStackID (const StackID &stack_id) - { - if (stack_id.IsValid()) - return GetStackFrameList()->GetFrameWithStackID (stack_id); - return lldb::StackFrameSP(); - } + //------------------------------------------------------------------ + /// 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 nullptr if all symbols are allowed. + /// + //------------------------------------------------------------------ + const RegularExpression *GetSymbolsToAvoidRegexp(); - uint32_t - GetSelectedFrameIndex () - { - return GetStackFrameList()->GetSelectedFrameIndex(); - } + FileSpecList &GetLibrariesToAvoid() const; - lldb::StackFrameSP - GetSelectedFrame (); + bool GetTraceEnabledState() const; - uint32_t - SetSelectedFrame (lldb_private::StackFrame *frame, bool broadcast = false); + bool GetStepInAvoidsNoDebug() const; - bool - SetSelectedFrameByIndex (uint32_t frame_idx, bool broadcast = false); + bool GetStepOutAvoidsNoDebug() const; +}; - bool - SetSelectedFrameByIndexNoisily (uint32_t frame_idx, Stream &output_stream); +typedef std::shared_ptr<ThreadProperties> ThreadPropertiesSP; - void - SetDefaultFileAndLineToSelectedFrame() - { - GetStackFrameList()->SetDefaultFileAndLineToSelectedFrame(); - } +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) + }; - virtual lldb::RegisterContextSP - GetRegisterContext () = 0; + static ConstString &GetStaticBroadcasterClass(); - virtual lldb::RegisterContextSP - CreateRegisterContextForFrame (StackFrame *frame) = 0; - - virtual void - ClearStackFrames (); + ConstString &GetBroadcasterClass() const override { + return GetStaticBroadcasterClass(); + } - virtual bool - SetBackingThread (const lldb::ThreadSP &thread_sp) - { - return false; - } - - virtual lldb::ThreadSP - GetBackingThread () const - { - return lldb::ThreadSP(); - } + class ThreadEventData : public EventData { + public: + ThreadEventData(const lldb::ThreadSP thread_sp); - 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. - } + ThreadEventData(const lldb::ThreadSP thread_sp, const StackID &stack_id); - void - DumpUsingSettingsFormat (Stream &strm, uint32_t frame_idx); - - bool - GetDescription (Stream &s, lldb::DescriptionLevel level, bool print_json_thread, bool print_json_stopinfo); - - //------------------------------------------------------------------ - /// 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. - /// - /// @param[in] tls_file_addr - /// The thread local address in module - /// @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, lldb::addr_t tls_file_addr); - - //------------------------------------------------------------------ - /// 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 nullptr 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 nullptr 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 nullptr 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); - - // Helper function that takes a LineEntry to step, insted of an AddressRange. This may combine multiple - // LineEntries of the same source line number to step over a longer address range in a single operation. - virtual lldb::ThreadPlanSP - QueueThreadPlanForStepOverRange (bool abort_other_plans, - const LineEntry &line_entry, - 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 nullptr 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); - - // Helper function that takes a LineEntry to step, insted of an AddressRange. This may combine multiple - // LineEntries of the same source line number to step over a longer address range in a single operation. - virtual lldb::ThreadPlanSP - QueueThreadPlanForStepInRange (bool abort_other_plans, - const LineEntry &line_entry, - 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 nullptr 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. - /// - /// @param[in] continue_to_next_branch - /// Normally this will enqueue a plan that will put a breakpoint on the return address and continue - /// to there. If continue_to_next_branch is true, this is an operation not involving the user -- - /// e.g. stepping "next" in a source line and we instruction stepped into another function -- - /// so instead of putting a breakpoint on the return address, advance the breakpoint to the - /// end of the source line that is doing the call, or until the next flow control instruction. - /// If the return value from the function call is to be retrieved / displayed to the user, you must stop - /// on the return address. The return value may be stored in volatile registers which are overwritten - /// before the next branch instruction. - /// - /// @return - /// A shared pointer to the newly queued thread plan, or nullptr 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, - bool continue_to_next_branch = false); - - //------------------------------------------------------------------ - /// 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 nullptr 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 nullptr 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); - - virtual lldb::ThreadPlanSP - QueueThreadPlanForStepScripted (bool abort_other_plans, - const char *class_name, - bool stop_other_threads); - - //------------------------------------------------------------------ - // 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(); - - //------------------------------------------------------------------ - /// 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 ExpressionVariableSP, 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::ExpressionVariableSP - 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); - - //------------------------------------------------------------------ - /// Discards the plans queued on the plan stack of the current thread up to and - /// including the plan in that matches \a thread_index counting only - /// the non-Private plans. - /// - /// @param[in] up_to_plan_sp - /// Discard all plans up to and including this user plan given by this index. - /// - /// @return - /// \b true if there was a thread plan with that user index, \b false otherwise. - //------------------------------------------------------------------ - bool - DiscardUserThreadPlansUpToIndex (uint32_t thread_index); - - //------------------------------------------------------------------ - /// Prints the current plan stack. - /// - /// @param[in] s - /// The stream to which to dump the plan stack info. - /// - //------------------------------------------------------------------ - void - DumpThreadPlans (Stream *s, - lldb::DescriptionLevel desc_level = lldb::eDescriptionLevelVerbose, - bool include_internal = true, - bool ignore_boring = false) 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 (); - } + ThreadEventData(); - //------------------------------------------------------------------ - // 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(); - } + ~ThreadEventData() override; - //------------------------------------------------------------------ - // lldb::ExecutionContextScope pure virtual functions - //------------------------------------------------------------------ - lldb::TargetSP - CalculateTarget() override; - - lldb::ProcessSP - CalculateProcess() override; - - lldb::ThreadSP - CalculateThread() override; - - lldb::StackFrameSP - CalculateStackFrame() override; - - void - CalculateExecutionContext(ExecutionContext &exe_ctx) override; - - 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; - } + static const ConstString &GetFlavorString(); - // 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; + const ConstString &GetFlavor() const override { + return ThreadEventData::GetFlavorString(); } - 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; + void Dump(Stream *s) const override; + + 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; + }; + + //------------------------------------------------------------------ + /// 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); + + ~Thread() override; + + static void SettingsInitialize(); + + static void SettingsTerminate(); + + static const ThreadPropertiesSP &GetGlobalProperties(); + + 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); + + //------------------------------------------------------------------ + /// Sets the USER resume state for this thread. If you set a thread to + /// suspended with + /// this API, it won't take part in any of the arbitration for ShouldResume, + /// and will stay + /// suspended even when other threads do get to run. + /// + /// N.B. This is not the state that is used internally by thread plans to + /// implement + /// staying on one thread while stepping over a breakpoint, etc. The is the + /// TemporaryResume state, and if you are implementing some bit of strategy in + /// the stepping + /// machinery you should be using that state and not the user resume state. + /// + /// 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. + /// @return + /// The User resume state for this thread. + //------------------------------------------------------------------ + void SetResumeState(lldb::StateType state, bool override_suspend = false) { + if (m_resume_state == lldb::eStateSuspended && !override_suspend) + return; + m_resume_state = state; + } + + //------------------------------------------------------------------ + /// Gets the USER resume state for this thread. This is not the same as what + /// this thread is going to do for any particular step, however if this thread + /// returns eStateSuspended, then the process control logic will never allow + /// this + /// thread to run. + /// + /// @return + /// The User resume state for this thread. + //------------------------------------------------------------------ + lldb::StateType GetResumeState() const { return m_resume_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(); + + bool StopInfoIsUpToDate() const; + + // 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 nullptr; } + + //------------------------------------------------------------------ + /// 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 nullptr; } + + virtual void SetName(const char *name) {} + + //------------------------------------------------------------------ + /// Whether this thread can be associated with a libdispatch queue + /// + /// The Thread may know if it is associated with a libdispatch queue, + /// it may know definitively that it is NOT associated with a libdispatch + /// queue, or it may be unknown whether it is associated with a libdispatch + /// queue. + /// + /// @return + /// eLazyBoolNo if this thread is definitely not associated with a + /// libdispatch queue (e.g. on a non-Darwin system where GCD aka + /// libdispatch is not available). + /// + /// eLazyBoolYes this thread is associated with a libdispatch queue. + /// + /// eLazyBoolCalculate this thread may be associated with a libdispatch + /// queue but the thread doesn't know one way or the other. + //------------------------------------------------------------------ + virtual lldb_private::LazyBool GetAssociatedWithLibdispatchQueue() { + return eLazyBoolNo; + } + + virtual void SetAssociatedWithLibdispatchQueue( + lldb_private::LazyBool associated_with_libdispatch_queue) {} + + //------------------------------------------------------------------ + /// 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 process. + /// + /// @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 + /// nullptr. + //------------------------------------------------------------------ + virtual const char *GetQueueName() { return nullptr; } + + virtual void SetQueueName(const char *name) {} + + //------------------------------------------------------------------ + /// Retrieve the Queue kind for the queue currently using this Thread + /// + /// If this Thread is doing work on behalf of a libdispatch/GCD queue, + /// retrieve the Queue kind - either eQueueKindSerial or + /// eQueueKindConcurrent, indicating that this queue processes work + /// items serially or concurrently. + /// + /// @return + /// The Queue kind, if the Thread subclass implements this, else + /// eQueueKindUnknown. + //------------------------------------------------------------------ + virtual lldb::QueueKind GetQueueKind() { return lldb::eQueueKindUnknown; } + + virtual void SetQueueKind(lldb::QueueKind kind) {} + + //------------------------------------------------------------------ + /// 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 void SetQueueLibdispatchQueueAddress(lldb::addr_t dispatch_queue_t) {} + + //------------------------------------------------------------------ + /// Whether this Thread already has all the Queue information cached or not + /// + /// A Thread may be associated with a libdispatch work Queue at a given + /// public stop event. If so, the thread can satisify requests like + /// GetQueueLibdispatchQueueAddress, GetQueueKind, GetQueueName, and + /// GetQueueID + /// either from information from the remote debug stub when it is initially + /// created, or it can query the SystemRuntime for that information. + /// + /// This method allows the SystemRuntime to discover if a thread has this + /// information already, instead of calling the thread to get the information + /// and having the thread call the SystemRuntime again. + //------------------------------------------------------------------ + virtual bool ThreadHasQueueInformation() const { return false; } + + 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 = nullptr); + + 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(); + + 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. + } + + // If stop_format is true, this will be the form used when we print stop info. + // If false, it will be the form we use for thread list and co. + void DumpUsingSettingsFormat(Stream &strm, uint32_t frame_idx, + bool stop_format); + + bool GetDescription(Stream &s, lldb::DescriptionLevel level, + bool print_json_thread, bool print_json_stopinfo); + + //------------------------------------------------------------------ + /// 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. + /// + /// @param[in] tls_file_addr + /// The thread local address in module + /// @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, + lldb::addr_t tls_file_addr); + + //------------------------------------------------------------------ + /// 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 nullptr 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 nullptr 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 nullptr 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); + + // Helper function that takes a LineEntry to step, insted of an AddressRange. + // This may combine multiple + // LineEntries of the same source line number to step over a longer address + // range in a single operation. + virtual lldb::ThreadPlanSP QueueThreadPlanForStepOverRange( + bool abort_other_plans, const LineEntry &line_entry, + 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 nullptr 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); + + // Helper function that takes a LineEntry to step, insted of an AddressRange. + // This may combine multiple + // LineEntries of the same source line number to step over a longer address + // range in a single operation. + virtual lldb::ThreadPlanSP QueueThreadPlanForStepInRange( + bool abort_other_plans, const LineEntry &line_entry, + 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 nullptr 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. + /// + /// @param[in] continue_to_next_branch + /// Normally this will enqueue a plan that will put a breakpoint on the + /// return address and continue + /// to there. If continue_to_next_branch is true, this is an operation not + /// involving the user -- + /// e.g. stepping "next" in a source line and we instruction stepped into + /// another function -- + /// so instead of putting a breakpoint on the return address, advance the + /// breakpoint to the + /// end of the source line that is doing the call, or until the next flow + /// control instruction. + /// If the return value from the function call is to be retrieved / + /// displayed to the user, you must stop + /// on the return address. The return value may be stored in volatile + /// registers which are overwritten + /// before the next branch instruction. + /// + /// @return + /// A shared pointer to the newly queued thread plan, or nullptr 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, bool continue_to_next_branch = false); + + //------------------------------------------------------------------ + /// 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 nullptr 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 nullptr 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); + + virtual lldb::ThreadPlanSP + QueueThreadPlanForStepScripted(bool abort_other_plans, const char *class_name, + bool stop_other_threads); + + //------------------------------------------------------------------ + // 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(); + + //------------------------------------------------------------------ + /// 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 ExpressionVariableSP, 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::ExpressionVariableSP 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); + + //------------------------------------------------------------------ + /// Discards the plans queued on the plan stack of the current thread up to + /// and + /// including the plan in that matches \a thread_index counting only + /// the non-Private plans. + /// + /// @param[in] up_to_plan_sp + /// Discard all plans up to and including this user plan given by this + /// index. + /// + /// @return + /// \b true if there was a thread plan with that user index, \b false + /// otherwise. + //------------------------------------------------------------------ + bool DiscardUserThreadPlansUpToIndex(uint32_t thread_index); + + //------------------------------------------------------------------ + /// Prints the current plan stack. + /// + /// @param[in] s + /// The stream to which to dump the plan stack info. + /// + //------------------------------------------------------------------ + void DumpThreadPlans( + Stream *s, + lldb::DescriptionLevel desc_level = lldb::eDescriptionLevelVerbose, + bool include_internal = true, bool ignore_boring = false) 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 + //------------------------------------------------------------------ + lldb::TargetSP CalculateTarget() override; + + lldb::ProcessSP CalculateProcess() override; + + lldb::ThreadSP CalculateThread() override; + + lldb::StackFrameSP CalculateStackFrame() override; + + void CalculateExecutionContext(ExecutionContext &exe_ctx) override; + + 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, + bool stop_format); + + 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(); - } + 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(); + + void SetTemporaryResumeState(lldb::StateType new_state) { + m_temporary_resume_state = new_state; + } + + void FunctionOptimizationWarning(lldb_private::StackFrame *frame); + + //------------------------------------------------------------------ + // 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 + uint32_t m_stop_info_override_stop_id; // The stop ID containing the last time + // the stop info was checked against + // the stop info override + 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 std::recursive_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 std::recursive_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; - lldb::StackFrameListSP - GetStackFrameList (); - - void - SetTemporaryResumeState(lldb::StateType new_state) - { - m_temporary_resume_state = new_state; - } - - void - FunctionOptimizationWarning (lldb_private::StackFrame *frame); - - //------------------------------------------------------------------ - // 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 - uint32_t m_stop_info_override_stop_id; // The stop ID containing the last time the stop info was checked against the stop info override - 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 std::recursive_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 std::recursive_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 + 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 private: - bool - PlanIsBasePlan (ThreadPlan *plan_ptr); + bool PlanIsBasePlan(ThreadPlan *plan_ptr); + + void BroadcastSelectedFrameChange(StackID &new_frame_id); - void - BroadcastSelectedFrameChange(StackID &new_frame_id); - - DISALLOW_COPY_AND_ASSIGN (Thread); + DISALLOW_COPY_AND_ASSIGN(Thread); }; } // namespace lldb_private |