xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h (revision 061da546b983eb767bad15e67af1174fb0bcf31c)
1*061da546Spatrick //===-- GDBRemoteClientBase.h -----------------------------------*- C++ -*-===//
2*061da546Spatrick //
3*061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*061da546Spatrick //
7*061da546Spatrick //===----------------------------------------------------------------------===//
8*061da546Spatrick 
9*061da546Spatrick #ifndef liblldb_GDBRemoteClientBase_h_
10*061da546Spatrick #define liblldb_GDBRemoteClientBase_h_
11*061da546Spatrick 
12*061da546Spatrick #include "GDBRemoteCommunication.h"
13*061da546Spatrick 
14*061da546Spatrick #include <condition_variable>
15*061da546Spatrick 
16*061da546Spatrick namespace lldb_private {
17*061da546Spatrick namespace process_gdb_remote {
18*061da546Spatrick 
19*061da546Spatrick class GDBRemoteClientBase : public GDBRemoteCommunication {
20*061da546Spatrick public:
21*061da546Spatrick   struct ContinueDelegate {
22*061da546Spatrick     virtual ~ContinueDelegate();
23*061da546Spatrick     virtual void HandleAsyncStdout(llvm::StringRef out) = 0;
24*061da546Spatrick     virtual void HandleAsyncMisc(llvm::StringRef data) = 0;
25*061da546Spatrick     virtual void HandleStopReply() = 0;
26*061da546Spatrick 
27*061da546Spatrick     /// Process asynchronously-received structured data.
28*061da546Spatrick     ///
29*061da546Spatrick     /// \param[in] data
30*061da546Spatrick     ///   The complete data packet, expected to start with JSON-async.
31*061da546Spatrick     virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0;
32*061da546Spatrick   };
33*061da546Spatrick 
34*061da546Spatrick   GDBRemoteClientBase(const char *comm_name, const char *listener_name);
35*061da546Spatrick 
36*061da546Spatrick   bool SendAsyncSignal(int signo);
37*061da546Spatrick 
38*061da546Spatrick   bool Interrupt();
39*061da546Spatrick 
40*061da546Spatrick   lldb::StateType SendContinuePacketAndWaitForResponse(
41*061da546Spatrick       ContinueDelegate &delegate, const UnixSignals &signals,
42*061da546Spatrick       llvm::StringRef payload, StringExtractorGDBRemote &response);
43*061da546Spatrick 
44*061da546Spatrick   PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload,
45*061da546Spatrick                                             StringExtractorGDBRemote &response,
46*061da546Spatrick                                             bool send_async);
47*061da546Spatrick 
48*061da546Spatrick   PacketResult SendPacketAndReceiveResponseWithOutputSupport(
49*061da546Spatrick       llvm::StringRef payload, StringExtractorGDBRemote &response,
50*061da546Spatrick       bool send_async,
51*061da546Spatrick       llvm::function_ref<void(llvm::StringRef)> output_callback);
52*061da546Spatrick 
53*061da546Spatrick   bool SendvContPacket(llvm::StringRef payload,
54*061da546Spatrick                        StringExtractorGDBRemote &response);
55*061da546Spatrick 
56*061da546Spatrick   class Lock {
57*061da546Spatrick   public:
58*061da546Spatrick     Lock(GDBRemoteClientBase &comm, bool interrupt);
59*061da546Spatrick     ~Lock();
60*061da546Spatrick 
61*061da546Spatrick     explicit operator bool() { return m_acquired; }
62*061da546Spatrick 
63*061da546Spatrick     // Whether we had to interrupt the continue thread to acquire the
64*061da546Spatrick     // connection.
65*061da546Spatrick     bool DidInterrupt() const { return m_did_interrupt; }
66*061da546Spatrick 
67*061da546Spatrick   private:
68*061da546Spatrick     std::unique_lock<std::recursive_mutex> m_async_lock;
69*061da546Spatrick     GDBRemoteClientBase &m_comm;
70*061da546Spatrick     bool m_acquired;
71*061da546Spatrick     bool m_did_interrupt;
72*061da546Spatrick 
73*061da546Spatrick     void SyncWithContinueThread(bool interrupt);
74*061da546Spatrick   };
75*061da546Spatrick 
76*061da546Spatrick protected:
77*061da546Spatrick   PacketResult
78*061da546Spatrick   SendPacketAndWaitForResponseNoLock(llvm::StringRef payload,
79*061da546Spatrick                                      StringExtractorGDBRemote &response);
80*061da546Spatrick 
81*061da546Spatrick   virtual void OnRunPacketSent(bool first);
82*061da546Spatrick 
83*061da546Spatrick private:
84*061da546Spatrick   /// Variables handling synchronization between the Continue thread and any
85*061da546Spatrick   /// other threads wishing to send packets over the connection. Either the
86*061da546Spatrick   /// continue thread has control over the connection (m_is_running == true) or
87*061da546Spatrick   /// the connection is free for an arbitrary number of other senders to take
88*061da546Spatrick   /// which indicate their interest by incrementing m_async_count.
89*061da546Spatrick   ///
90*061da546Spatrick   /// Semantics of individual states:
91*061da546Spatrick   ///
92*061da546Spatrick   /// - m_continue_packet == false, m_async_count == 0:
93*061da546Spatrick   ///   connection is free
94*061da546Spatrick   /// - m_continue_packet == true, m_async_count == 0:
95*061da546Spatrick   ///   only continue thread is present
96*061da546Spatrick   /// - m_continue_packet == true, m_async_count > 0:
97*061da546Spatrick   ///   continue thread has control, async threads should interrupt it and wait
98*061da546Spatrick   ///   for it to set m_continue_packet to false
99*061da546Spatrick   /// - m_continue_packet == false, m_async_count > 0:
100*061da546Spatrick   ///   async threads have control, continue thread needs to wait for them to
101*061da546Spatrick   ///   finish (m_async_count goes down to 0).
102*061da546Spatrick   /// @{
103*061da546Spatrick   std::mutex m_mutex;
104*061da546Spatrick   std::condition_variable m_cv;
105*061da546Spatrick 
106*061da546Spatrick   /// Packet with which to resume after an async interrupt. Can be changed by
107*061da546Spatrick   /// an async thread e.g. to inject a signal.
108*061da546Spatrick   std::string m_continue_packet;
109*061da546Spatrick 
110*061da546Spatrick   /// When was the interrupt packet sent. Used to make sure we time out if the
111*061da546Spatrick   /// stub does not respond to interrupt requests.
112*061da546Spatrick   std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time;
113*061da546Spatrick 
114*061da546Spatrick   /// Number of threads interested in sending.
115*061da546Spatrick   uint32_t m_async_count;
116*061da546Spatrick 
117*061da546Spatrick   /// Whether the continue thread has control.
118*061da546Spatrick   bool m_is_running;
119*061da546Spatrick 
120*061da546Spatrick   /// Whether we should resume after a stop.
121*061da546Spatrick   bool m_should_stop;
122*061da546Spatrick   /// @}
123*061da546Spatrick 
124*061da546Spatrick   /// This handles the synchronization between individual async threads. For
125*061da546Spatrick   /// now they just use a simple mutex.
126*061da546Spatrick   std::recursive_mutex m_async_mutex;
127*061da546Spatrick 
128*061da546Spatrick   bool ShouldStop(const UnixSignals &signals,
129*061da546Spatrick                   StringExtractorGDBRemote &response);
130*061da546Spatrick 
131*061da546Spatrick   class ContinueLock {
132*061da546Spatrick   public:
133*061da546Spatrick     enum class LockResult { Success, Cancelled, Failed };
134*061da546Spatrick 
135*061da546Spatrick     explicit ContinueLock(GDBRemoteClientBase &comm);
136*061da546Spatrick     ~ContinueLock();
137*061da546Spatrick     explicit operator bool() { return m_acquired; }
138*061da546Spatrick 
139*061da546Spatrick     LockResult lock();
140*061da546Spatrick 
141*061da546Spatrick     void unlock();
142*061da546Spatrick 
143*061da546Spatrick   private:
144*061da546Spatrick     GDBRemoteClientBase &m_comm;
145*061da546Spatrick     bool m_acquired;
146*061da546Spatrick   };
147*061da546Spatrick };
148*061da546Spatrick 
149*061da546Spatrick } // namespace process_gdb_remote
150*061da546Spatrick } // namespace lldb_private
151*061da546Spatrick 
152*061da546Spatrick #endif // liblldb_GDBRemoteCommunicationClient_h_
153