10b57cec5SDimitry Andric //===-- WatchpointOptions.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 
95ffd83dbSDimitry Andric #ifndef LLDB_BREAKPOINT_WATCHPOINTOPTIONS_H
105ffd83dbSDimitry Andric #define LLDB_BREAKPOINT_WATCHPOINTOPTIONS_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include <memory>
130b57cec5SDimitry Andric #include <string>
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "lldb/Utility/Baton.h"
160b57cec5SDimitry Andric #include "lldb/Utility/StringList.h"
170b57cec5SDimitry Andric #include "lldb/lldb-private.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric namespace lldb_private {
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric /// \class WatchpointOptions WatchpointOptions.h
220b57cec5SDimitry Andric /// "lldb/Breakpoint/WatchpointOptions.h" Class that manages the options on a
230b57cec5SDimitry Andric /// watchpoint.
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric class WatchpointOptions {
260b57cec5SDimitry Andric public:
270b57cec5SDimitry Andric   // Constructors and Destructors
280b57cec5SDimitry Andric   /// Default constructor.  The watchpoint is enabled, and has no condition,
290b57cec5SDimitry Andric   /// callback, ignore count, etc...
300b57cec5SDimitry Andric   WatchpointOptions();
310b57cec5SDimitry Andric   WatchpointOptions(const WatchpointOptions &rhs);
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric   static WatchpointOptions *CopyOptionsNoCallback(WatchpointOptions &rhs);
340b57cec5SDimitry Andric   /// This constructor allows you to specify all the watchpoint options.
350b57cec5SDimitry Andric   ///
360b57cec5SDimitry Andric   /// \param[in] callback
370b57cec5SDimitry Andric   ///    This is the plugin for some code that gets run, returns \b true if we
380b57cec5SDimitry Andric   ///    are to stop.
390b57cec5SDimitry Andric   ///
400b57cec5SDimitry Andric   /// \param[in] baton
410b57cec5SDimitry Andric   ///    Client data that will get passed to the callback.
420b57cec5SDimitry Andric   ///
430b57cec5SDimitry Andric   /// \param[in] thread_id
440b57cec5SDimitry Andric   ///    Only stop if \a thread_id hits the watchpoint.
450b57cec5SDimitry Andric   WatchpointOptions(WatchpointHitCallback callback, void *baton,
460b57cec5SDimitry Andric                     lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   virtual ~WatchpointOptions();
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   // Operators
510b57cec5SDimitry Andric   const WatchpointOptions &operator=(const WatchpointOptions &rhs);
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   // Callbacks
540b57cec5SDimitry Andric   //
550b57cec5SDimitry Andric   // Watchpoint callbacks come in two forms, synchronous and asynchronous.
560b57cec5SDimitry Andric   // Synchronous callbacks will get run before any of the thread plans are
570b57cec5SDimitry Andric   // consulted, and if they return false the target will continue "under the
580b57cec5SDimitry Andric   // radar" of the thread plans.  There are a couple of restrictions to
590b57cec5SDimitry Andric   // synchronous callbacks: 1) They should NOT resume the target themselves.
600b57cec5SDimitry Andric   // Just return false if you want the target to restart. 2) Watchpoints with
610b57cec5SDimitry Andric   // synchronous callbacks can't have conditions (or rather, they can have
625f757f3fSDimitry Andric   // them, but they won't do anything.  Ditto with ignore counts, etc...
635f757f3fSDimitry Andric   // You are supposed to control that all through the callback.
640b57cec5SDimitry Andric   // Asynchronous callbacks get run as part of the "ShouldStop" logic in the
650b57cec5SDimitry Andric   // thread plan.  The logic there is:
660b57cec5SDimitry Andric   //   a) If the watchpoint is thread specific and not for this thread, continue
670b57cec5SDimitry Andric   //      w/o running the callback.
680b57cec5SDimitry Andric   //   b) If the ignore count says we shouldn't stop, then ditto.
690b57cec5SDimitry Andric   //   c) If the condition says we shouldn't stop, then ditto.
700b57cec5SDimitry Andric   //   d) Otherwise, the callback will get run, and if it returns true we will
710b57cec5SDimitry Andric   //      stop, and if false we won't.
720b57cec5SDimitry Andric   //  The asynchronous callback can run the target itself, but at present that
735f757f3fSDimitry Andric   //  should be the last action the callback does.  We will relax this
745f757f3fSDimitry Andric   //  condition at some point, but it will take a bit of plumbing to get
750b57cec5SDimitry Andric   //  that to work.
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric   /// Adds a callback to the watchpoint option set.
780b57cec5SDimitry Andric   ///
790b57cec5SDimitry Andric   /// \param[in] callback
800b57cec5SDimitry Andric   ///    The function to be called when the watchpoint gets hit.
810b57cec5SDimitry Andric   ///
820b57cec5SDimitry Andric   /// \param[in] baton_sp
830b57cec5SDimitry Andric   ///    A baton which will get passed back to the callback when it is invoked.
840b57cec5SDimitry Andric   ///
850b57cec5SDimitry Andric   /// \param[in] synchronous
865f757f3fSDimitry Andric   ///    Whether this is a synchronous or asynchronous callback.
875f757f3fSDimitry Andric   ///    See discussion above.
880b57cec5SDimitry Andric   void SetCallback(WatchpointHitCallback callback,
890b57cec5SDimitry Andric                    const lldb::BatonSP &baton_sp, bool synchronous = false);
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// Remove the callback from this option set.
920b57cec5SDimitry Andric   void ClearCallback();
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   // The rest of these functions are meant to be used only within the
950b57cec5SDimitry Andric   // watchpoint handling mechanism.
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   /// Use this function to invoke the callback for a specific stop.
980b57cec5SDimitry Andric   ///
990b57cec5SDimitry Andric   /// \param[in] context
1000b57cec5SDimitry Andric   ///    The context in which the callback is to be invoked.  This includes the
1015f757f3fSDimitry Andric   ///    stop event, the execution context of the stop (since you might hit
1025f757f3fSDimitry Andric   ///    the same watchpoint on multiple threads) and whether we are currently
1035f757f3fSDimitry Andric   ///    executing synchronous or asynchronous callbacks.
1040b57cec5SDimitry Andric   ///
1050b57cec5SDimitry Andric   /// \param[in] watch_id
1060b57cec5SDimitry Andric   ///    The watchpoint ID that owns this option set.
1070b57cec5SDimitry Andric   ///
1080b57cec5SDimitry Andric   /// \return
1090b57cec5SDimitry Andric   ///     The callback return value.
1100b57cec5SDimitry Andric   bool InvokeCallback(StoppointCallbackContext *context,
1110b57cec5SDimitry Andric                       lldb::user_id_t watch_id);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   /// Used in InvokeCallback to tell whether it is the right time to run this
1140b57cec5SDimitry Andric   /// kind of callback.
1150b57cec5SDimitry Andric   ///
1160b57cec5SDimitry Andric   /// \return
1170b57cec5SDimitry Andric   ///     The synchronicity of our callback.
IsCallbackSynchronous()1180b57cec5SDimitry Andric   bool IsCallbackSynchronous() { return m_callback_is_synchronous; }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   /// Fetch the baton from the callback.
1210b57cec5SDimitry Andric   ///
1220b57cec5SDimitry Andric   /// \return
1230b57cec5SDimitry Andric   ///     The baton.
1240b57cec5SDimitry Andric   Baton *GetBaton();
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   /// Fetch a const version of the baton from the callback.
1270b57cec5SDimitry Andric   ///
1280b57cec5SDimitry Andric   /// \return
1290b57cec5SDimitry Andric   ///     The baton.
1300b57cec5SDimitry Andric   const Baton *GetBaton() const;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   /// Return the current thread spec for this option. This will return nullptr
1335f757f3fSDimitry Andric   /// if the no thread specifications have been set for this WatchpointOptions
1345f757f3fSDimitry Andric   /// yet.
1355f757f3fSDimitry Andric   ///
1360b57cec5SDimitry Andric   /// \return
1370b57cec5SDimitry Andric   ///     The thread specification pointer for this option, or nullptr if none
1385f757f3fSDimitry Andric   ///     has been set yet.
1390b57cec5SDimitry Andric   const ThreadSpec *GetThreadSpecNoCreate() const;
1400b57cec5SDimitry Andric 
1415f757f3fSDimitry Andric   /// Returns a pointer to the ThreadSpec for this option, creating it if it
1420b57cec5SDimitry Andric   /// hasn't been created already. This API is used for setting the
1435f757f3fSDimitry Andric   /// ThreadSpec items for this WatchpointOptions.
1440b57cec5SDimitry Andric   ThreadSpec *GetThreadSpec();
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   void SetThreadID(lldb::tid_t thread_id);
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   void GetDescription(Stream *s, lldb::DescriptionLevel level) const;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   /// Get description for callback only.
1510b57cec5SDimitry Andric   void GetCallbackDescription(Stream *s, lldb::DescriptionLevel level) const;
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   /// Returns true if the watchpoint option has a callback set.
1540b57cec5SDimitry Andric   bool HasCallback();
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   /// This is the default empty callback.
1570b57cec5SDimitry Andric   /// \return
1580b57cec5SDimitry Andric   ///     The thread id for which the watchpoint hit will stop,
1590b57cec5SDimitry Andric   ///     LLDB_INVALID_THREAD_ID for all threads.
1600b57cec5SDimitry Andric   static bool NullCallback(void *baton, StoppointCallbackContext *context,
1610b57cec5SDimitry Andric                            lldb::user_id_t watch_id);
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   struct CommandData {
16481ad6265SDimitry Andric     CommandData() = default;
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric     ~CommandData() = default;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric     StringList user_source;
1690b57cec5SDimitry Andric     std::string script_source;
170fe6060f1SDimitry Andric     bool stop_on_error = true;
1710b57cec5SDimitry Andric   };
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   class CommandBaton : public TypedBaton<CommandData> {
1740b57cec5SDimitry Andric   public:
CommandBaton(std::unique_ptr<CommandData> Data)1750b57cec5SDimitry Andric     CommandBaton(std::unique_ptr<CommandData> Data)
1760b57cec5SDimitry Andric         : TypedBaton(std::move(Data)) {}
1770b57cec5SDimitry Andric 
178480093f4SDimitry Andric     void GetDescription(llvm::raw_ostream &s, lldb::DescriptionLevel level,
179480093f4SDimitry Andric                         unsigned indentation) const override;
1800b57cec5SDimitry Andric   };
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric private:
1830b57cec5SDimitry Andric   WatchpointHitCallback m_callback;  // This is the callback function pointer
1840b57cec5SDimitry Andric   lldb::BatonSP m_callback_baton_sp; // This is the client data for the callback
185fe6060f1SDimitry Andric   bool m_callback_is_synchronous = false;
1860b57cec5SDimitry Andric   std::unique_ptr<ThreadSpec>
1870b57cec5SDimitry Andric       m_thread_spec_up; // Thread for which this watchpoint will take
1880b57cec5SDimitry Andric };
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric } // namespace lldb_private
1910b57cec5SDimitry Andric 
1925ffd83dbSDimitry Andric #endif // LLDB_BREAKPOINT_WATCHPOINTOPTIONS_H
193