xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Target/ThreadPlanShouldStopHere.h (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
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