LLDB  mainline
GDBRemoteClientBase.h
Go to the documentation of this file.
1 //===-- GDBRemoteClientBase.h -----------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H
10 #define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H
11 
12 #include "GDBRemoteCommunication.h"
13 
14 #include <condition_variable>
15 
16 namespace lldb_private {
17 namespace process_gdb_remote {
18 
20 public:
22  virtual ~ContinueDelegate();
23  virtual void HandleAsyncStdout(llvm::StringRef out) = 0;
24  virtual void HandleAsyncMisc(llvm::StringRef data) = 0;
25  virtual void HandleStopReply() = 0;
26 
27  /// Process asynchronously-received structured data.
28  ///
29  /// \param[in] data
30  /// The complete data packet, expected to start with JSON-async.
31  virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0;
32  };
33 
34  GDBRemoteClientBase(const char *comm_name, const char *listener_name);
35 
36  bool SendAsyncSignal(int signo, std::chrono::seconds interrupt_timeout);
37 
38  bool Interrupt(std::chrono::seconds interrupt_timeout);
39 
41  ContinueDelegate &delegate, const UnixSignals &signals,
42  llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
43  StringExtractorGDBRemote &response);
44 
45  // If interrupt_timeout == 0 seconds, don't interrupt the target.
46  // Only send the packet if the target is stopped.
47  // If you want to use this mode, use the fact that the timeout is defaulted
48  // so it's clear from the call-site that you are using no-interrupt.
49  // If it is non-zero, interrupt the target if it is running, and
50  // send the packet.
51  // It the target doesn't respond within the given timeout, it returns
52  // ErrorReplyTimeout.
54  llvm::StringRef payload, StringExtractorGDBRemote &response,
55  std::chrono::seconds interrupt_timeout = std::chrono::seconds(0));
56 
58  llvm::StringRef payload, StringExtractorGDBRemote &response,
59  std::chrono::seconds interrupt_timeout,
60  llvm::function_ref<void(llvm::StringRef)> output_callback);
61 
62  bool SendvContPacket(llvm::StringRef payload,
63  std::chrono::seconds interrupt_timeout,
64  StringExtractorGDBRemote &response);
65 
66  class Lock {
67  public:
68  // If interrupt_timeout == 0 seconds, only take the lock if the target is
69  // not running. If using this option, use the fact that the
70  // interrupt_timeout is defaulted so it will be obvious at the call site
71  // that you are choosing this mode. If it is non-zero, interrupt the target
72  // if it is running, waiting for the given timeout for the interrupt to
73  // succeed.
75  std::chrono::seconds interrupt_timeout = std::chrono::seconds(0));
76  ~Lock();
77 
78  explicit operator bool() { return m_acquired; }
79 
80  // Whether we had to interrupt the continue thread to acquire the
81  // connection.
82  bool DidInterrupt() const { return m_did_interrupt; }
83 
84  private:
85  std::unique_lock<std::recursive_mutex> m_async_lock;
87  std::chrono::seconds m_interrupt_timeout;
88  bool m_acquired;
90 
92  };
93 
94 protected:
96  SendPacketAndWaitForResponseNoLock(llvm::StringRef payload,
97  StringExtractorGDBRemote &response);
98 
99  virtual void OnRunPacketSent(bool first);
100 
101 private:
102  /// Variables handling synchronization between the Continue thread and any
103  /// other threads wishing to send packets over the connection. Either the
104  /// continue thread has control over the connection (m_is_running == true) or
105  /// the connection is free for an arbitrary number of other senders to take
106  /// which indicate their interest by incrementing m_async_count.
107  ///
108  /// Semantics of individual states:
109  ///
110  /// - m_continue_packet == false, m_async_count == 0:
111  /// connection is free
112  /// - m_continue_packet == true, m_async_count == 0:
113  /// only continue thread is present
114  /// - m_continue_packet == true, m_async_count > 0:
115  /// continue thread has control, async threads should interrupt it and wait
116  /// for it to set m_continue_packet to false
117  /// - m_continue_packet == false, m_async_count > 0:
118  /// async threads have control, continue thread needs to wait for them to
119  /// finish (m_async_count goes down to 0).
120  /// @{
121  std::mutex m_mutex;
122  std::condition_variable m_cv;
123 
124  /// Packet with which to resume after an async interrupt. Can be changed by
125  /// an async thread e.g. to inject a signal.
127 
128  /// When was the interrupt packet sent. Used to make sure we time out if the
129  /// stub does not respond to interrupt requests.
130  std::chrono::time_point<std::chrono::steady_clock> m_interrupt_endpoint;
131 
132  /// Number of threads interested in sending.
134 
135  /// Whether the continue thread has control.
137 
138  /// Whether we should resume after a stop.
140  /// @}
141 
142  /// This handles the synchronization between individual async threads. For
143  /// now they just use a simple mutex.
144  std::recursive_mutex m_async_mutex;
145 
146  bool ShouldStop(const UnixSignals &signals,
147  StringExtractorGDBRemote &response);
148 
149  class ContinueLock {
150  public:
151  enum class LockResult { Success, Cancelled, Failed };
152 
153  explicit ContinueLock(GDBRemoteClientBase &comm);
154  ~ContinueLock();
155  explicit operator bool() { return m_acquired; }
156 
157  LockResult lock();
158 
159  void unlock();
160 
161  private:
164  };
165 };
166 
167 } // namespace process_gdb_remote
168 } // namespace lldb_private
169 
170 #endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECLIENTBASE_H
lldb_private::process_gdb_remote::GDBRemoteClientBase::m_is_running
bool m_is_running
Whether the continue thread has control.
Definition: GDBRemoteClientBase.h:136
lldb_private::process_gdb_remote::GDBRemoteClientBase::SendvContPacket
bool SendvContPacket(llvm::StringRef payload, std::chrono::seconds interrupt_timeout, StringExtractorGDBRemote &response)
Definition: GDBRemoteClientBase.cpp:252
lldb_private::process_gdb_remote::GDBRemoteClientBase::ShouldStop
bool ShouldStop(const UnixSignals &signals, StringExtractorGDBRemote &response)
Definition: GDBRemoteClientBase.cpp:278
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate
virtual ~ContinueDelegate()
lldb_private::process_gdb_remote::GDBRemoteClientBase::m_async_mutex
std::recursive_mutex m_async_mutex
This handles the synchronization between individual async threads.
Definition: GDBRemoteClientBase.h:144
lldb_private::process_gdb_remote::GDBRemoteClientBase::m_async_count
uint32_t m_async_count
Number of threads interested in sending.
Definition: GDBRemoteClientBase.h:133
lldb_private::process_gdb_remote::GDBRemoteClientBase::OnRunPacketSent
virtual void OnRunPacketSent(bool first)
Definition: GDBRemoteClientBase.cpp:309
lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult
PacketResult
Definition: GDBRemoteCommunication.h:92
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::unlock
void unlock()
Definition: GDBRemoteClientBase.cpp:328
lldb_private::process_gdb_remote::GDBRemoteClientBase::m_mutex
std::mutex m_mutex
Variables handling synchronization between the Continue thread and any other threads wishing to send ...
Definition: GDBRemoteClientBase.h:121
lldb_private::process_gdb_remote::GDBRemoteCommunication
Definition: GDBRemoteCommunication.h:82
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::m_async_lock
std::unique_lock< std::recursive_mutex > m_async_lock
Definition: GDBRemoteClientBase.h:85
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::LockResult::Failed
@ Failed
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueDelegate
Definition: GDBRemoteClientBase.h:21
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueDelegate::HandleAsyncStructuredDataPacket
virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data)=0
Process asynchronously-received structured data.
lldb_private::process_gdb_remote::GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock
PacketResult SendPacketAndWaitForResponseNoLock(llvm::StringRef payload, StringExtractorGDBRemote &response)
Definition: GDBRemoteClientBase.cpp:224
lldb_private::process_gdb_remote::GDBRemoteClientBase::GDBRemoteClientBase
GDBRemoteClientBase(const char *comm_name, const char *listener_name)
Definition: GDBRemoteClientBase.cpp:34
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::ContinueLock
ContinueLock(GDBRemoteClientBase &comm)
Definition: GDBRemoteClientBase.cpp:318
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueDelegate::HandleAsyncMisc
virtual void HandleAsyncMisc(llvm::StringRef data)=0
lldb_private::process_gdb_remote::GDBRemoteClientBase::m_cv
std::condition_variable m_cv
Definition: GDBRemoteClientBase.h:122
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::DidInterrupt
bool DidInterrupt() const
Definition: GDBRemoteClientBase.h:82
lldb_private::process_gdb_remote::GDBRemoteClientBase::SendAsyncSignal
bool SendAsyncSignal(int signo, std::chrono::seconds interrupt_timeout)
Definition: GDBRemoteClientBase.cpp:161
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::m_acquired
bool m_acquired
Definition: GDBRemoteClientBase.h:163
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueDelegate::HandleAsyncStdout
virtual void HandleAsyncStdout(llvm::StringRef out)=0
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::m_comm
GDBRemoteClientBase & m_comm
Definition: GDBRemoteClientBase.h:86
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::m_interrupt_timeout
std::chrono::seconds m_interrupt_timeout
Definition: GDBRemoteClientBase.h:87
lldb_private::process_gdb_remote::GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport
PacketResult SendPacketAndReceiveResponseWithOutputSupport(llvm::StringRef payload, StringExtractorGDBRemote &response, std::chrono::seconds interrupt_timeout, llvm::function_ref< void(llvm::StringRef)> output_callback)
Definition: GDBRemoteClientBase.cpp:200
lldb_private::UnixSignals
Definition: UnixSignals.h:22
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::m_acquired
bool m_acquired
Definition: GDBRemoteClientBase.h:88
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::LockResult
LockResult
Definition: GDBRemoteClientBase.h:151
string
string(SUBSTRING ${p} 10 -1 pStripped) if($
Definition: Plugins/CMakeLists.txt:39
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::m_comm
GDBRemoteClientBase & m_comm
Definition: GDBRemoteClientBase.h:162
lldb_private::process_gdb_remote::GDBRemoteClientBase::SendContinuePacketAndWaitForResponse
lldb::StateType SendContinuePacketAndWaitForResponse(ContinueDelegate &delegate, const UnixSignals &signals, llvm::StringRef payload, std::chrono::seconds interrupt_timeout, StringExtractorGDBRemote &response)
Definition: GDBRemoteClientBase.cpp:39
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::LockResult::Cancelled
@ Cancelled
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::~Lock
~Lock()
Definition: GDBRemoteClientBase.cpp:408
lldb_private::process_gdb_remote::GDBRemoteClientBase
Definition: GDBRemoteClientBase.h:19
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueDelegate::HandleStopReply
virtual void HandleStopReply()=0
uint32_t
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock
Definition: GDBRemoteClientBase.h:149
lldb_private::process_gdb_remote::GDBRemoteClientBase::m_interrupt_endpoint
std::chrono::time_point< std::chrono::steady_clock > m_interrupt_endpoint
When was the interrupt packet sent.
Definition: GDBRemoteClientBase.h:130
lldb_private::process_gdb_remote::GDBRemoteClientBase::SendPacketAndWaitForResponse
PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response, std::chrono::seconds interrupt_timeout=std::chrono::seconds(0))
Definition: GDBRemoteClientBase.cpp:182
GDBRemoteCommunication.h
lldb_private::process_gdb_remote::GDBRemoteClientBase::m_should_stop
bool m_should_stop
Whether we should resume after a stop.
Definition: GDBRemoteClientBase.h:139
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::SyncWithContinueThread
void SyncWithContinueThread()
Definition: GDBRemoteClientBase.cpp:377
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock
Definition: GDBRemoteClientBase.h:66
lldb_private::process_gdb_remote::GDBRemoteClientBase::Interrupt
bool Interrupt(std::chrono::seconds interrupt_timeout)
Definition: GDBRemoteClientBase.cpp:173
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::LockResult::Success
@ Success
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::~ContinueLock
~ContinueLock()
Definition: GDBRemoteClientBase.cpp:323
lldb_private::process_gdb_remote::GDBRemoteClientBase::m_continue_packet
std::string m_continue_packet
Packet with which to resume after an async interrupt.
Definition: GDBRemoteClientBase.h:126
StringExtractorGDBRemote
Definition: StringExtractorGDBRemote.h:21
lldb_private::process_gdb_remote::GDBRemoteClientBase::ContinueLock::lock
LockResult lock()
Definition: GDBRemoteClientBase.cpp:339
lldb::StateType
StateType
Process and Thread States.
Definition: lldb-enumerations.h:73
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::Lock
Lock(GDBRemoteClientBase &comm, std::chrono::seconds interrupt_timeout=std::chrono::seconds(0))
Definition: GDBRemoteClientBase.cpp:367
lldb_private::process_gdb_remote::GDBRemoteClientBase::Lock::m_did_interrupt
bool m_did_interrupt
Definition: GDBRemoteClientBase.h:89