1 //===-- ThreadPlanShouldStopHere.h ------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_TARGET_THREADPLANSHOULDSTOPHERE_H 10 #define LLDB_TARGET_THREADPLANSHOULDSTOPHERE_H 11 12 #include "lldb/Target/ThreadPlan.h" 13 14 namespace lldb_private { 15 16 // This is an interface that ThreadPlans can adopt to allow flexible 17 // modifications of the behavior when a thread plan comes to a place where it 18 // would ordinarily stop. If such modification makes sense for your plan, 19 // inherit from this class, and when you would be about to stop (in your 20 // ShouldStop method), call InvokeShouldStopHereCallback, passing in the frame 21 // comparison between where the step operation started and where you arrived. 22 // If it returns true, then QueueStepOutFromHere will queue the plan to execute 23 // instead of stopping. 24 // 25 // The classic example of the use of this is ThreadPlanStepInRange not stopping 26 // in frames that have no debug information. 27 // 28 // This class also defines a set of flags to control general aspects of this 29 // "ShouldStop" behavior. 30 // A class implementing this protocol needs to define a default set of flags, 31 // and can provide access to 32 // changing that default flag set if it wishes. 33 34 class ThreadPlanShouldStopHere { 35 public: 36 struct ThreadPlanShouldStopHereCallbacks { ThreadPlanShouldStopHereCallbacksThreadPlanShouldStopHereCallbacks37 ThreadPlanShouldStopHereCallbacks() { 38 should_stop_here_callback = nullptr; 39 step_from_here_callback = nullptr; 40 } 41 ThreadPlanShouldStopHereCallbacksThreadPlanShouldStopHereCallbacks42 ThreadPlanShouldStopHereCallbacks( 43 ThreadPlanShouldStopHereCallback should_stop, 44 ThreadPlanStepFromHereCallback step_from_here) { 45 should_stop_here_callback = should_stop; 46 step_from_here_callback = step_from_here; 47 } 48 ClearThreadPlanShouldStopHereCallbacks49 void Clear() { 50 should_stop_here_callback = nullptr; 51 step_from_here_callback = nullptr; 52 } 53 54 ThreadPlanShouldStopHereCallback should_stop_here_callback; 55 ThreadPlanStepFromHereCallback step_from_here_callback; 56 }; 57 58 enum { 59 eNone = 0, 60 eAvoidInlines = (1 << 0), 61 eStepInAvoidNoDebug = (1 << 1), 62 eStepOutAvoidNoDebug = (1 << 2), 63 eStepOutPastThunks = (1 << 3) 64 }; 65 66 // Constructors and Destructors 67 ThreadPlanShouldStopHere(ThreadPlan *owner); 68 69 ThreadPlanShouldStopHere(ThreadPlan *owner, 70 const ThreadPlanShouldStopHereCallbacks *callbacks, 71 void *baton = nullptr); 72 virtual ~ThreadPlanShouldStopHere(); 73 74 // Set the ShouldStopHere callbacks. Pass in null to clear them and have no 75 // special behavior (though you can also call ClearShouldStopHereCallbacks 76 // for that purpose. If you pass in a valid pointer, it will adopt the non- 77 // null fields, and any null fields will be set to the default values. 78 79 void SetShouldStopHereCallbacks(const ThreadPlanShouldStopHereCallbacks * callbacks,void * baton)80 SetShouldStopHereCallbacks(const ThreadPlanShouldStopHereCallbacks *callbacks, 81 void *baton) { 82 if (callbacks) { 83 m_callbacks = *callbacks; 84 if (!m_callbacks.should_stop_here_callback) 85 m_callbacks.should_stop_here_callback = 86 ThreadPlanShouldStopHere::DefaultShouldStopHereCallback; 87 if (!m_callbacks.step_from_here_callback) 88 m_callbacks.step_from_here_callback = 89 ThreadPlanShouldStopHere::DefaultStepFromHereCallback; 90 } else { 91 ClearShouldStopHereCallbacks(); 92 } 93 m_baton = baton; 94 } 95 ClearShouldStopHereCallbacks()96 void ClearShouldStopHereCallbacks() { m_callbacks.Clear(); } 97 98 bool InvokeShouldStopHereCallback(lldb::FrameComparison operation, 99 Status &status); 100 101 lldb::ThreadPlanSP 102 CheckShouldStopHereAndQueueStepOut(lldb::FrameComparison operation, 103 Status &status); 104 GetFlags()105 lldb_private::Flags &GetFlags() { return m_flags; } 106 GetFlags()107 const lldb_private::Flags &GetFlags() const { return m_flags; } 108 109 protected: 110 static bool DefaultShouldStopHereCallback(ThreadPlan *current_plan, 111 Flags &flags, 112 lldb::FrameComparison operation, 113 Status &status, void *baton); 114 115 static lldb::ThreadPlanSP 116 DefaultStepFromHereCallback(ThreadPlan *current_plan, Flags &flags, 117 lldb::FrameComparison operation, Status &status, 118 void *baton); 119 120 virtual lldb::ThreadPlanSP 121 QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation, 122 Status &status); 123 124 // Implement this, and call it in the plan's constructor to set the default 125 // flags. 126 virtual void SetFlagsToDefault() = 0; 127 128 ThreadPlanShouldStopHereCallbacks m_callbacks; 129 void *m_baton; 130 ThreadPlan *m_owner; 131 lldb_private::Flags m_flags; 132 133 private: 134 ThreadPlanShouldStopHere(const ThreadPlanShouldStopHere &) = delete; 135 const ThreadPlanShouldStopHere & 136 operator=(const ThreadPlanShouldStopHere &) = delete; 137 }; 138 139 } // namespace lldb_private 140 141 #endif // LLDB_TARGET_THREADPLANSHOULDSTOPHERE_H 142