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