| //===-- ThreadPlanShouldStopHere.h ------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef liblldb_ThreadPlanShouldStopHere_h_ |
| #define liblldb_ThreadPlanShouldStopHere_h_ |
| |
| // C Includes |
| // C++ Includes |
| // Other libraries and framework includes |
| // Project includes |
| #include "lldb/Target/ThreadPlan.h" |
| |
| namespace lldb_private { |
| |
| // This is an interface that ThreadPlans can adopt to allow flexible |
| // modifications of the behavior when a thread plan comes to a place where it |
| // would ordinarily stop. If such modification makes sense for your plan, |
| // inherit from this class, and when you would be about to stop (in your |
| // ShouldStop method), call InvokeShouldStopHereCallback, passing in the frame |
| // comparison between where the step operation started and where you arrived. |
| // If it returns true, then QueueStepOutFromHere will queue the plan to execute |
| // instead of stopping. |
| // |
| // The classic example of the use of this is ThreadPlanStepInRange not stopping |
| // in frames that have no debug information. |
| // |
| // This class also defines a set of flags to control general aspects of this |
| // "ShouldStop" behavior. |
| // A class implementing this protocol needs to define a default set of flags, |
| // and can provide access to |
| // changing that default flag set if it wishes. |
| |
| class ThreadPlanShouldStopHere { |
| public: |
| struct ThreadPlanShouldStopHereCallbacks { |
| ThreadPlanShouldStopHereCallbacks() { |
| should_stop_here_callback = nullptr; |
| step_from_here_callback = nullptr; |
| } |
| |
| ThreadPlanShouldStopHereCallbacks( |
| ThreadPlanShouldStopHereCallback should_stop, |
| ThreadPlanStepFromHereCallback step_from_here) { |
| should_stop_here_callback = should_stop; |
| step_from_here_callback = step_from_here; |
| } |
| |
| void Clear() { |
| should_stop_here_callback = nullptr; |
| step_from_here_callback = nullptr; |
| } |
| |
| ThreadPlanShouldStopHereCallback should_stop_here_callback; |
| ThreadPlanStepFromHereCallback step_from_here_callback; |
| }; |
| |
| enum { |
| eNone = 0, |
| eAvoidInlines = (1 << 0), |
| eStepInAvoidNoDebug = (1 << 1), |
| eStepOutAvoidNoDebug = (1 << 2) |
| }; |
| |
| //------------------------------------------------------------------ |
| // Constructors and Destructors |
| //------------------------------------------------------------------ |
| ThreadPlanShouldStopHere(ThreadPlan *owner); |
| |
| ThreadPlanShouldStopHere(ThreadPlan *owner, |
| const ThreadPlanShouldStopHereCallbacks *callbacks, |
| void *baton = nullptr); |
| virtual ~ThreadPlanShouldStopHere(); |
| |
| // Set the ShouldStopHere callbacks. Pass in null to clear them and have no |
| // special behavior (though you can also call ClearShouldStopHereCallbacks |
| // for that purpose. If you pass in a valid pointer, it will adopt the non- |
| // null fields, and any null fields will be set to the default values. |
| |
| void |
| SetShouldStopHereCallbacks(const ThreadPlanShouldStopHereCallbacks *callbacks, |
| void *baton) { |
| if (callbacks) { |
| m_callbacks = *callbacks; |
| if (!m_callbacks.should_stop_here_callback) |
| m_callbacks.should_stop_here_callback = |
| ThreadPlanShouldStopHere::DefaultShouldStopHereCallback; |
| if (!m_callbacks.step_from_here_callback) |
| m_callbacks.step_from_here_callback = |
| ThreadPlanShouldStopHere::DefaultStepFromHereCallback; |
| } else { |
| ClearShouldStopHereCallbacks(); |
| } |
| m_baton = baton; |
| } |
| |
| void ClearShouldStopHereCallbacks() { m_callbacks.Clear(); } |
| |
| bool InvokeShouldStopHereCallback(lldb::FrameComparison operation); |
| |
| lldb::ThreadPlanSP |
| CheckShouldStopHereAndQueueStepOut(lldb::FrameComparison operation); |
| |
| lldb_private::Flags &GetFlags() { return m_flags; } |
| |
| const lldb_private::Flags &GetFlags() const { return m_flags; } |
| |
| protected: |
| static bool DefaultShouldStopHereCallback(ThreadPlan *current_plan, |
| Flags &flags, |
| lldb::FrameComparison operation, |
| void *baton); |
| |
| static lldb::ThreadPlanSP |
| DefaultStepFromHereCallback(ThreadPlan *current_plan, Flags &flags, |
| lldb::FrameComparison operation, void *baton); |
| |
| virtual lldb::ThreadPlanSP |
| QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation); |
| |
| // Implement this, and call it in the plan's constructor to set the default |
| // flags. |
| virtual void SetFlagsToDefault() = 0; |
| |
| ThreadPlanShouldStopHereCallbacks m_callbacks; |
| void *m_baton; |
| ThreadPlan *m_owner; |
| lldb_private::Flags m_flags; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ThreadPlanShouldStopHere); |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // liblldb_ThreadPlanShouldStopHere_h_ |