1 //===-- GDBRemoteClientBase.cpp -------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "GDBRemoteClientBase.h"
11 #include "llvm/ADT/StringExtras.h"
13 #include "lldb/Target/UnixSignals.h"
14 #include "lldb/Utility/LLDBAssert.h"
16 #include "ProcessGDBRemoteLog.h"
19 using namespace lldb_private
;
20 using namespace lldb_private::process_gdb_remote
;
21 using namespace std::chrono
;
23 // When we've sent a continue packet and are waiting for the target to stop,
24 // we wake up the wait with this interval to make sure the stub hasn't gone
25 // away while we were waiting.
26 static const seconds
kWakeupInterval(5);
28 /////////////////////////
29 // GDBRemoteClientBase //
30 /////////////////////////
32 GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default;
34 GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name
)
35 : GDBRemoteCommunication(), Broadcaster(nullptr, comm_name
),
36 m_async_count(0), m_is_running(false), m_should_stop(false) {}
38 StateType
GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
39 ContinueDelegate
&delegate
, const UnixSignals
&signals
,
40 llvm::StringRef payload
, std::chrono::seconds interrupt_timeout
,
41 StringExtractorGDBRemote
&response
) {
42 Log
*log
= GetLog(GDBRLog::Process
);
46 std::lock_guard
<std::mutex
> lock(m_mutex
);
47 m_continue_packet
= std::string(payload
);
48 m_should_stop
= false;
50 ContinueLock
cont_lock(*this);
53 OnRunPacketSent(true);
54 // The main ReadPacket loop wakes up at computed_timeout intervals, just to
55 // check that the connection hasn't dropped. When we wake up we also check
56 // whether there is an interrupt request that has reached its endpoint.
57 // If we want a shorter interrupt timeout that kWakeupInterval, we need to
58 // choose the shorter interval for the wake up as well.
59 std::chrono::seconds computed_timeout
= std::min(interrupt_timeout
,
62 PacketResult read_result
= ReadPacket(response
, computed_timeout
, false);
63 // Reset the computed_timeout to the default value in case we are going
65 computed_timeout
= std::min(interrupt_timeout
, kWakeupInterval
);
66 switch (read_result
) {
67 case PacketResult::ErrorReplyTimeout
: {
68 std::lock_guard
<std::mutex
> lock(m_mutex
);
69 if (m_async_count
== 0) {
72 auto cur_time
= steady_clock::now();
73 if (cur_time
>= m_interrupt_endpoint
)
76 // We woke up and found an interrupt is in flight, but we haven't
77 // exceeded the interrupt wait time. So reset the wait time to the
78 // time left till the interrupt timeout. But don't wait longer
79 // than our wakeup timeout.
80 auto new_wait
= m_interrupt_endpoint
- cur_time
;
81 computed_timeout
= std::min(kWakeupInterval
,
82 std::chrono::duration_cast
<std::chrono::seconds
>(new_wait
));
87 case PacketResult::Success
:
90 LLDB_LOGF(log
, "GDBRemoteClientBase::%s () ReadPacket(...) => false",
97 const char stop_type
= response
.GetChar();
98 LLDB_LOGF(log
, "GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__
,
99 response
.GetStringRef().data());
107 return eStateInvalid
;
109 LLDB_LOGF(log
, "GDBRemoteClientBase::%s () unrecognized async packet",
111 return eStateInvalid
;
113 std::string inferior_stdout
;
114 response
.GetHexByteString(inferior_stdout
);
115 delegate
.HandleAsyncStdout(inferior_stdout
);
119 delegate
.HandleAsyncMisc(
120 llvm::StringRef(response
.GetStringRef()).substr(1));
123 delegate
.HandleAsyncStructuredDataPacket(response
.GetStringRef());
127 // Do this with the continue lock held.
128 const bool should_stop
= ShouldStop(signals
, response
);
129 response
.SetFilePos(0);
131 // The packet we should resume with. In the future we should check our
132 // thread list and "do the right thing" for new threads that show up
133 // while we stop and run async packets. Setting the packet to 'c' to
134 // continue all threads is the right thing to do 99.99% of the time
135 // because if a thread was single stepping, and we sent an interrupt, we
136 // will notice above that we didn't stop due to an interrupt but stopped
137 // due to stepping and we would _not_ continue. This packet may get
138 // modified by the async actions (e.g. to send a signal).
139 m_continue_packet
= 'c';
142 delegate
.HandleStopReply();
144 return eStateStopped
;
146 switch (cont_lock
.lock()) {
147 case ContinueLock::LockResult::Success
:
149 case ContinueLock::LockResult::Failed
:
150 return eStateInvalid
;
151 case ContinueLock::LockResult::Cancelled
:
152 return eStateStopped
;
154 OnRunPacketSent(false);
160 bool GDBRemoteClientBase::SendAsyncSignal(
161 int signo
, std::chrono::seconds interrupt_timeout
) {
162 Lock
lock(*this, interrupt_timeout
);
163 if (!lock
|| !lock
.DidInterrupt())
166 m_continue_packet
= 'C';
167 m_continue_packet
+= llvm::hexdigit((signo
/ 16) % 16);
168 m_continue_packet
+= llvm::hexdigit(signo
% 16);
172 bool GDBRemoteClientBase::Interrupt(std::chrono::seconds interrupt_timeout
) {
173 Lock
lock(*this, interrupt_timeout
);
174 if (!lock
.DidInterrupt())
176 m_should_stop
= true;
180 GDBRemoteCommunication::PacketResult
181 GDBRemoteClientBase::SendPacketAndWaitForResponse(
182 llvm::StringRef payload
, StringExtractorGDBRemote
&response
,
183 std::chrono::seconds interrupt_timeout
) {
184 Lock
lock(*this, interrupt_timeout
);
186 if (Log
*log
= GetLog(GDBRLog::Process
))
188 "GDBRemoteClientBase::%s failed to get mutex, not sending "
190 __FUNCTION__
, int(payload
.size()), payload
.data());
191 return PacketResult::ErrorSendFailed
;
194 return SendPacketAndWaitForResponseNoLock(payload
, response
);
197 GDBRemoteCommunication::PacketResult
198 GDBRemoteClientBase::ReadPacketWithOutputSupport(
199 StringExtractorGDBRemote
&response
, Timeout
<std::micro
> timeout
,
200 bool sync_on_timeout
,
201 llvm::function_ref
<void(llvm::StringRef
)> output_callback
) {
202 auto result
= ReadPacket(response
, timeout
, sync_on_timeout
);
203 while (result
== PacketResult::Success
&& response
.IsNormalResponse() &&
204 response
.PeekChar() == 'O') {
207 if (response
.GetHexByteString(output
))
208 output_callback(output
);
209 result
= ReadPacket(response
, timeout
, sync_on_timeout
);
214 GDBRemoteCommunication::PacketResult
215 GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
216 llvm::StringRef payload
, StringExtractorGDBRemote
&response
,
217 std::chrono::seconds interrupt_timeout
,
218 llvm::function_ref
<void(llvm::StringRef
)> output_callback
) {
219 Lock
lock(*this, interrupt_timeout
);
221 if (Log
*log
= GetLog(GDBRLog::Process
))
223 "GDBRemoteClientBase::%s failed to get mutex, not sending "
225 __FUNCTION__
, int(payload
.size()), payload
.data());
226 return PacketResult::ErrorSendFailed
;
229 PacketResult packet_result
= SendPacketNoLock(payload
);
230 if (packet_result
!= PacketResult::Success
)
231 return packet_result
;
233 return ReadPacketWithOutputSupport(response
, GetPacketTimeout(), true,
237 GDBRemoteCommunication::PacketResult
238 GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
239 llvm::StringRef payload
, StringExtractorGDBRemote
&response
) {
240 PacketResult packet_result
= SendPacketNoLock(payload
);
241 if (packet_result
!= PacketResult::Success
)
242 return packet_result
;
244 const size_t max_response_retries
= 3;
245 for (size_t i
= 0; i
< max_response_retries
; ++i
) {
246 packet_result
= ReadPacket(response
, GetPacketTimeout(), true);
247 // Make sure we received a response
248 if (packet_result
!= PacketResult::Success
)
249 return packet_result
;
250 // Make sure our response is valid for the payload that was sent
251 if (response
.ValidateResponse())
252 return packet_result
;
253 // Response says it wasn't valid
254 Log
*log
= GetLog(GDBRLog::Packets
);
257 "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
258 int(payload
.size()), payload
.data(), response
.GetStringRef().data(),
259 (i
== (max_response_retries
- 1))
260 ? "using invalid response and giving up"
261 : "ignoring response and waiting for another");
263 return packet_result
;
266 bool GDBRemoteClientBase::ShouldStop(const UnixSignals
&signals
,
267 StringExtractorGDBRemote
&response
) {
268 std::lock_guard
<std::mutex
> lock(m_mutex
);
270 if (m_async_count
== 0)
271 return true; // We were not interrupted. The process stopped on its own.
273 // Older debugserver stubs (before April 2016) can return two stop-reply
274 // packets in response to a ^C packet. Additionally, all debugservers still
275 // return two stop replies if the inferior stops due to some other reason
276 // before the remote stub manages to interrupt it. We need to wait for this
277 // additional packet to make sure the packet sequence does not get skewed.
278 StringExtractorGDBRemote extra_stop_reply_packet
;
279 ReadPacket(extra_stop_reply_packet
, milliseconds(100), false);
281 // Interrupting is typically done using SIGSTOP or SIGINT, so if the process
282 // stops with some other signal, we definitely want to stop.
283 const uint8_t signo
= response
.GetHexU8(UINT8_MAX
);
284 if (signo
!= signals
.GetSignalNumberFromName("SIGSTOP") &&
285 signo
!= signals
.GetSignalNumberFromName("SIGINT"))
288 // We probably only stopped to perform some async processing, so continue
289 // after that is done.
290 // TODO: This is not 100% correct, as the process may have been stopped with
291 // SIGINT or SIGSTOP that was not caused by us (e.g. raise(SIGINT)). This will
292 // normally cause a stop, but if it's done concurrently with a async
293 // interrupt, that stop will get eaten (llvm.org/pr20231).
297 void GDBRemoteClientBase::OnRunPacketSent(bool first
) {
299 BroadcastEvent(eBroadcastBitRunPacketSent
, nullptr);
302 ///////////////////////////////////////
303 // GDBRemoteClientBase::ContinueLock //
304 ///////////////////////////////////////
306 GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase
&comm
)
307 : m_comm(comm
), m_acquired(false) {
311 GDBRemoteClientBase::ContinueLock::~ContinueLock() {
316 void GDBRemoteClientBase::ContinueLock::unlock() {
317 lldbassert(m_acquired
);
319 std::unique_lock
<std::mutex
> lock(m_comm
.m_mutex
);
320 m_comm
.m_is_running
= false;
322 m_comm
.m_cv
.notify_all();
326 GDBRemoteClientBase::ContinueLock::LockResult
327 GDBRemoteClientBase::ContinueLock::lock() {
328 Log
*log
= GetLog(GDBRLog::Process
);
329 LLDB_LOGF(log
, "GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
330 __FUNCTION__
, m_comm
.m_continue_packet
.c_str());
332 lldbassert(!m_acquired
);
333 std::unique_lock
<std::mutex
> lock(m_comm
.m_mutex
);
334 m_comm
.m_cv
.wait(lock
, [this] { return m_comm
.m_async_count
== 0; });
335 if (m_comm
.m_should_stop
) {
336 m_comm
.m_should_stop
= false;
337 LLDB_LOGF(log
, "GDBRemoteClientBase::ContinueLock::%s() cancelled",
339 return LockResult::Cancelled
;
341 if (m_comm
.SendPacketNoLock(m_comm
.m_continue_packet
) !=
342 PacketResult::Success
)
343 return LockResult::Failed
;
345 lldbassert(!m_comm
.m_is_running
);
346 m_comm
.m_is_running
= true;
348 return LockResult::Success
;
351 ///////////////////////////////
352 // GDBRemoteClientBase::Lock //
353 ///////////////////////////////
355 GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase
&comm
,
356 std::chrono::seconds interrupt_timeout
)
357 : m_async_lock(comm
.m_async_mutex
, std::defer_lock
), m_comm(comm
),
358 m_interrupt_timeout(interrupt_timeout
), m_acquired(false),
359 m_did_interrupt(false) {
360 SyncWithContinueThread();
365 void GDBRemoteClientBase::Lock::SyncWithContinueThread() {
366 Log
*log
= GetLog(GDBRLog::Process
|GDBRLog::Packets
);
367 std::unique_lock
<std::mutex
> lock(m_comm
.m_mutex
);
368 if (m_comm
.m_is_running
&& m_interrupt_timeout
== std::chrono::seconds(0))
369 return; // We were asked to avoid interrupting the sender. Lock is not
372 ++m_comm
.m_async_count
;
373 if (m_comm
.m_is_running
) {
374 if (m_comm
.m_async_count
== 1) {
375 // The sender has sent the continue packet and we are the first async
376 // packet. Let's interrupt it.
377 const char ctrl_c
= '\x03';
378 ConnectionStatus status
= eConnectionStatusSuccess
;
379 size_t bytes_written
= m_comm
.Write(&ctrl_c
, 1, status
, nullptr);
380 if (bytes_written
== 0) {
381 --m_comm
.m_async_count
;
382 LLDB_LOGF(log
, "GDBRemoteClientBase::Lock::Lock failed to send "
386 m_comm
.m_interrupt_endpoint
= steady_clock::now() + m_interrupt_timeout
;
388 log
->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
390 m_comm
.m_cv
.wait(lock
, [this] { return !m_comm
.m_is_running
; });
391 m_did_interrupt
= true;
396 GDBRemoteClientBase::Lock::~Lock() {
400 std::unique_lock
<std::mutex
> lock(m_comm
.m_mutex
);
401 --m_comm
.m_async_count
;
403 m_comm
.m_cv
.notify_one();