10b57cec5SDimitry Andric //===-- ThreadPlanShouldStopHere.h ------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 9*5ffd83dbSDimitry Andric #ifndef LLDB_TARGET_THREADPLANSHOULDSTOPHERE_H 10*5ffd83dbSDimitry Andric #define LLDB_TARGET_THREADPLANSHOULDSTOPHERE_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include "lldb/Target/ThreadPlan.h" 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric namespace lldb_private { 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric // This is an interface that ThreadPlans can adopt to allow flexible 170b57cec5SDimitry Andric // modifications of the behavior when a thread plan comes to a place where it 180b57cec5SDimitry Andric // would ordinarily stop. If such modification makes sense for your plan, 190b57cec5SDimitry Andric // inherit from this class, and when you would be about to stop (in your 200b57cec5SDimitry Andric // ShouldStop method), call InvokeShouldStopHereCallback, passing in the frame 210b57cec5SDimitry Andric // comparison between where the step operation started and where you arrived. 220b57cec5SDimitry Andric // If it returns true, then QueueStepOutFromHere will queue the plan to execute 230b57cec5SDimitry Andric // instead of stopping. 240b57cec5SDimitry Andric // 250b57cec5SDimitry Andric // The classic example of the use of this is ThreadPlanStepInRange not stopping 260b57cec5SDimitry Andric // in frames that have no debug information. 270b57cec5SDimitry Andric // 280b57cec5SDimitry Andric // This class also defines a set of flags to control general aspects of this 290b57cec5SDimitry Andric // "ShouldStop" behavior. 300b57cec5SDimitry Andric // A class implementing this protocol needs to define a default set of flags, 310b57cec5SDimitry Andric // and can provide access to 320b57cec5SDimitry Andric // changing that default flag set if it wishes. 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric class ThreadPlanShouldStopHere { 350b57cec5SDimitry Andric public: 360b57cec5SDimitry Andric struct ThreadPlanShouldStopHereCallbacks { ThreadPlanShouldStopHereCallbacksThreadPlanShouldStopHereCallbacks370b57cec5SDimitry Andric ThreadPlanShouldStopHereCallbacks() { 380b57cec5SDimitry Andric should_stop_here_callback = nullptr; 390b57cec5SDimitry Andric step_from_here_callback = nullptr; 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric ThreadPlanShouldStopHereCallbacksThreadPlanShouldStopHereCallbacks420b57cec5SDimitry Andric ThreadPlanShouldStopHereCallbacks( 430b57cec5SDimitry Andric ThreadPlanShouldStopHereCallback should_stop, 440b57cec5SDimitry Andric ThreadPlanStepFromHereCallback step_from_here) { 450b57cec5SDimitry Andric should_stop_here_callback = should_stop; 460b57cec5SDimitry Andric step_from_here_callback = step_from_here; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric ClearThreadPlanShouldStopHereCallbacks490b57cec5SDimitry Andric void Clear() { 500b57cec5SDimitry Andric should_stop_here_callback = nullptr; 510b57cec5SDimitry Andric step_from_here_callback = nullptr; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric ThreadPlanShouldStopHereCallback should_stop_here_callback; 550b57cec5SDimitry Andric ThreadPlanStepFromHereCallback step_from_here_callback; 560b57cec5SDimitry Andric }; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric enum { 590b57cec5SDimitry Andric eNone = 0, 600b57cec5SDimitry Andric eAvoidInlines = (1 << 0), 610b57cec5SDimitry Andric eStepInAvoidNoDebug = (1 << 1), 620b57cec5SDimitry Andric eStepOutAvoidNoDebug = (1 << 2) 630b57cec5SDimitry Andric }; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // Constructors and Destructors 660b57cec5SDimitry Andric ThreadPlanShouldStopHere(ThreadPlan *owner); 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric ThreadPlanShouldStopHere(ThreadPlan *owner, 690b57cec5SDimitry Andric const ThreadPlanShouldStopHereCallbacks *callbacks, 700b57cec5SDimitry Andric void *baton = nullptr); 710b57cec5SDimitry Andric virtual ~ThreadPlanShouldStopHere(); 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric // Set the ShouldStopHere callbacks. Pass in null to clear them and have no 740b57cec5SDimitry Andric // special behavior (though you can also call ClearShouldStopHereCallbacks 750b57cec5SDimitry Andric // for that purpose. If you pass in a valid pointer, it will adopt the non- 760b57cec5SDimitry Andric // null fields, and any null fields will be set to the default values. 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric void SetShouldStopHereCallbacks(const ThreadPlanShouldStopHereCallbacks * callbacks,void * baton)790b57cec5SDimitry Andric SetShouldStopHereCallbacks(const ThreadPlanShouldStopHereCallbacks *callbacks, 800b57cec5SDimitry Andric void *baton) { 810b57cec5SDimitry Andric if (callbacks) { 820b57cec5SDimitry Andric m_callbacks = *callbacks; 830b57cec5SDimitry Andric if (!m_callbacks.should_stop_here_callback) 840b57cec5SDimitry Andric m_callbacks.should_stop_here_callback = 850b57cec5SDimitry Andric ThreadPlanShouldStopHere::DefaultShouldStopHereCallback; 860b57cec5SDimitry Andric if (!m_callbacks.step_from_here_callback) 870b57cec5SDimitry Andric m_callbacks.step_from_here_callback = 880b57cec5SDimitry Andric ThreadPlanShouldStopHere::DefaultStepFromHereCallback; 890b57cec5SDimitry Andric } else { 900b57cec5SDimitry Andric ClearShouldStopHereCallbacks(); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric m_baton = baton; 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric ClearShouldStopHereCallbacks()950b57cec5SDimitry Andric void ClearShouldStopHereCallbacks() { m_callbacks.Clear(); } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric bool InvokeShouldStopHereCallback(lldb::FrameComparison operation, 980b57cec5SDimitry Andric Status &status); 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric lldb::ThreadPlanSP 1010b57cec5SDimitry Andric CheckShouldStopHereAndQueueStepOut(lldb::FrameComparison operation, 1020b57cec5SDimitry Andric Status &status); 1030b57cec5SDimitry Andric GetFlags()1040b57cec5SDimitry Andric lldb_private::Flags &GetFlags() { return m_flags; } 1050b57cec5SDimitry Andric GetFlags()1060b57cec5SDimitry Andric const lldb_private::Flags &GetFlags() const { return m_flags; } 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric protected: 1090b57cec5SDimitry Andric static bool DefaultShouldStopHereCallback(ThreadPlan *current_plan, 1100b57cec5SDimitry Andric Flags &flags, 1110b57cec5SDimitry Andric lldb::FrameComparison operation, 1120b57cec5SDimitry Andric Status &status, void *baton); 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric static lldb::ThreadPlanSP 1150b57cec5SDimitry Andric DefaultStepFromHereCallback(ThreadPlan *current_plan, Flags &flags, 1160b57cec5SDimitry Andric lldb::FrameComparison operation, Status &status, 1170b57cec5SDimitry Andric void *baton); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric virtual lldb::ThreadPlanSP 1200b57cec5SDimitry Andric QueueStepOutFromHerePlan(Flags &flags, lldb::FrameComparison operation, 1210b57cec5SDimitry Andric Status &status); 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric // Implement this, and call it in the plan's constructor to set the default 1240b57cec5SDimitry Andric // flags. 1250b57cec5SDimitry Andric virtual void SetFlagsToDefault() = 0; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric ThreadPlanShouldStopHereCallbacks m_callbacks; 1280b57cec5SDimitry Andric void *m_baton; 1290b57cec5SDimitry Andric ThreadPlan *m_owner; 1300b57cec5SDimitry Andric lldb_private::Flags m_flags; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric private: 133*5ffd83dbSDimitry Andric ThreadPlanShouldStopHere(const ThreadPlanShouldStopHere &) = delete; 134*5ffd83dbSDimitry Andric const ThreadPlanShouldStopHere & 135*5ffd83dbSDimitry Andric operator=(const ThreadPlanShouldStopHere &) = delete; 1360b57cec5SDimitry Andric }; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric } // namespace lldb_private 1390b57cec5SDimitry Andric 140*5ffd83dbSDimitry Andric #endif // LLDB_TARGET_THREADPLANSHOULDSTOPHERE_H 141