blob: af8db8e59e09b7efbb6dfecffdbe28c7b66a37f7 [file] [log] [blame]
Pavel Labath8c1b6bd2016-08-09 12:04:46 +00001//===-- GDBRemoteClientBase.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "GDBRemoteClientBase.h"
11
12#include "llvm/ADT/StringExtras.h"
13
Todd Fiala75930012016-08-19 04:21:48 +000014#include "lldb/Target/Process.h"
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000015#include "lldb/Target/UnixSignals.h"
16#include "lldb/Utility/LLDBAssert.h"
17
18#include "ProcessGDBRemoteLog.h"
19
20using namespace lldb;
21using namespace lldb_private;
22using namespace lldb_private::process_gdb_remote;
23
24static const std::chrono::seconds kInterruptTimeout(5);
25
26/////////////////////////
27// GDBRemoteClientBase //
28/////////////////////////
29
30GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default;
31
Kate Stoneb9c1b512016-09-06 20:57:50 +000032GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name,
33 const char *listener_name)
34 : GDBRemoteCommunication(comm_name, listener_name), m_async_count(0),
35 m_is_running(false), m_should_stop(false) {}
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000036
Kate Stoneb9c1b512016-09-06 20:57:50 +000037StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
38 ContinueDelegate &delegate, const UnixSignals &signals,
39 llvm::StringRef payload, StringExtractorGDBRemote &response) {
40 Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
41 response.Clear();
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000042
Kate Stoneb9c1b512016-09-06 20:57:50 +000043 {
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000044 std::lock_guard<std::mutex> lock(m_mutex);
Kate Stoneb9c1b512016-09-06 20:57:50 +000045 m_continue_packet = payload;
46 m_should_stop = false;
47 }
48 ContinueLock cont_lock(*this);
49 if (!cont_lock)
50 return eStateInvalid;
51 OnRunPacketSent(true);
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000052
Kate Stoneb9c1b512016-09-06 20:57:50 +000053 for (;;) {
54 PacketResult read_result = ReadPacket(
55 response,
56 std::chrono::duration_cast<std::chrono::microseconds>(kInterruptTimeout)
57 .count(),
58 false);
59 switch (read_result) {
60 case PacketResult::ErrorReplyTimeout: {
61 std::lock_guard<std::mutex> lock(m_mutex);
62 if (m_async_count == 0)
63 continue;
64 if (std::chrono::steady_clock::now() >=
65 m_interrupt_time + kInterruptTimeout)
66 return eStateInvalid;
67 }
68 case PacketResult::Success:
69 break;
70 default:
71 if (log)
72 log->Printf("GDBRemoteClientBase::%s () ReadPacket(...) => false",
73 __FUNCTION__);
74 return eStateInvalid;
75 }
76 if (response.Empty())
77 return eStateInvalid;
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000078
Kate Stoneb9c1b512016-09-06 20:57:50 +000079 const char stop_type = response.GetChar();
80 if (log)
81 log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
82 response.GetStringRef().c_str());
Pavel Labath8c1b6bd2016-08-09 12:04:46 +000083
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 switch (stop_type) {
85 case 'W':
86 case 'X':
87 return eStateExited;
88 case 'E':
89 // ERROR
90 return eStateInvalid;
91 default:
92 if (log)
93 log->Printf("GDBRemoteClientBase::%s () unrecognized async packet",
94 __FUNCTION__);
95 return eStateInvalid;
96 case 'O': {
97 std::string inferior_stdout;
98 response.GetHexByteString(inferior_stdout);
99 delegate.HandleAsyncStdout(inferior_stdout);
100 break;
101 }
102 case 'A':
103 delegate.HandleAsyncMisc(
104 llvm::StringRef(response.GetStringRef()).substr(1));
105 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106 case 'J':
Todd Fialafcdb1af2016-09-10 00:06:29 +0000107 delegate.HandleAsyncStructuredDataPacket(response.GetStringRef());
108 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 case 'T':
110 case 'S':
111 // Do this with the continue lock held.
112 const bool should_stop = ShouldStop(signals, response);
113 response.SetFilePos(0);
114
115 // The packet we should resume with. In the future
116 // we should check our thread list and "do the right thing"
117 // for new threads that show up while we stop and run async
118 // packets. Setting the packet to 'c' to continue all threads
119 // is the right thing to do 99.99% of the time because if a
120 // thread was single stepping, and we sent an interrupt, we
121 // will notice above that we didn't stop due to an interrupt
122 // but stopped due to stepping and we would _not_ continue.
123 // This packet may get modified by the async actions (e.g. to send a
124 // signal).
125 m_continue_packet = 'c';
126 cont_lock.unlock();
127
128 delegate.HandleStopReply();
129 if (should_stop)
130 return eStateStopped;
131
132 switch (cont_lock.lock()) {
133 case ContinueLock::LockResult::Success:
134 break;
135 case ContinueLock::LockResult::Failed:
136 return eStateInvalid;
137 case ContinueLock::LockResult::Cancelled:
138 return eStateStopped;
139 }
140 OnRunPacketSent(false);
141 break;
142 }
143 }
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000144}
145
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
147 Lock lock(*this, true);
148 if (!lock || !lock.DidInterrupt())
149 return false;
150
151 m_continue_packet = 'C';
152 m_continue_packet += llvm::hexdigit((signo / 16) % 16);
153 m_continue_packet += llvm::hexdigit(signo % 16);
154 return true;
155}
156
157bool GDBRemoteClientBase::Interrupt() {
158 Lock lock(*this, true);
159 if (!lock.DidInterrupt())
160 return false;
161 m_should_stop = true;
162 return true;
163}
164GDBRemoteCommunication::PacketResult
165GDBRemoteClientBase::SendPacketAndWaitForResponse(
166 llvm::StringRef payload, StringExtractorGDBRemote &response,
167 bool send_async) {
168 Lock lock(*this, send_async);
169 if (!lock) {
170 if (Log *log =
171 ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
172 log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending "
173 "packet '%.*s' (send_async=%d)",
174 __FUNCTION__, int(payload.size()), payload.data(),
175 send_async);
176 return PacketResult::ErrorSendFailed;
177 }
178
179 return SendPacketAndWaitForResponseNoLock(payload, response);
180}
181
182GDBRemoteCommunication::PacketResult
183GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
184 llvm::StringRef payload, StringExtractorGDBRemote &response) {
185 PacketResult packet_result = SendPacketNoLock(payload);
186 if (packet_result != PacketResult::Success)
187 return packet_result;
188
189 const size_t max_response_retries = 3;
190 for (size_t i = 0; i < max_response_retries; ++i) {
Pavel Labath3aa04912016-10-31 17:19:42 +0000191 packet_result = ReadPacket(
192 response, std::chrono::duration_cast<std::chrono::microseconds>(
193 GetPacketTimeout())
194 .count(),
195 true);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 // Make sure we received a response
197 if (packet_result != PacketResult::Success)
198 return packet_result;
199 // Make sure our response is valid for the payload that was sent
200 if (response.ValidateResponse())
201 return packet_result;
202 // Response says it wasn't valid
203 Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS);
204 if (log)
205 log->Printf(
206 "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
207 int(payload.size()), payload.data(), response.GetStringRef().c_str(),
208 (i == (max_response_retries - 1))
209 ? "using invalid response and giving up"
210 : "ignoring response and waiting for another");
211 }
212 return packet_result;
213}
214
215bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload,
216 StringExtractorGDBRemote &response) {
217 Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
218 if (log)
219 log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
220
221 // we want to lock down packet sending while we continue
222 Lock lock(*this, true);
223
224 if (log)
225 log->Printf(
226 "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s",
227 __FUNCTION__, int(payload.size()), payload.data());
228
229 if (SendPacketNoLock(payload) != PacketResult::Success)
230 return false;
231
232 OnRunPacketSent(true);
233
234 // wait for the response to the vCont
235 if (ReadPacket(response, UINT32_MAX, false) == PacketResult::Success) {
236 if (response.IsOKResponse())
237 return true;
238 }
239
240 return false;
241}
242bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
243 StringExtractorGDBRemote &response) {
244 std::lock_guard<std::mutex> lock(m_mutex);
245
246 if (m_async_count == 0)
247 return true; // We were not interrupted. The process stopped on its own.
248
249 // Older debugserver stubs (before April 2016) can return two
250 // stop-reply packets in response to a ^C packet.
251 // Additionally, all debugservers still return two stop replies if
252 // the inferior stops due to some other reason before the remote
253 // stub manages to interrupt it. We need to wait for this
254 // additional packet to make sure the packet sequence does not get
255 // skewed.
256 StringExtractorGDBRemote extra_stop_reply_packet;
257 uint32_t timeout_usec = 100000; // 100ms
258 ReadPacket(extra_stop_reply_packet, timeout_usec, false);
259
260 // Interrupting is typically done using SIGSTOP or SIGINT, so if
261 // the process stops with some other signal, we definitely want to
262 // stop.
263 const uint8_t signo = response.GetHexU8(UINT8_MAX);
264 if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
265 signo != signals.GetSignalNumberFromName("SIGINT"))
266 return true;
267
268 // We probably only stopped to perform some async processing, so continue
269 // after that is done.
270 // TODO: This is not 100% correct, as the process may have been stopped with
271 // SIGINT or SIGSTOP
272 // that was not caused by us (e.g. raise(SIGINT)). This will normally cause a
273 // stop, but if it's
274 // done concurrently with a async interrupt, that stop will get eaten
275 // (llvm.org/pr20231).
276 return false;
277}
278
279void GDBRemoteClientBase::OnRunPacketSent(bool first) {
280 if (first)
281 BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000282}
283
284///////////////////////////////////////
285// GDBRemoteClientBase::ContinueLock //
286///////////////////////////////////////
287
Kate Stoneb9c1b512016-09-06 20:57:50 +0000288GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm)
289 : m_comm(comm), m_acquired(false) {
290 lock();
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000291}
292
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293GDBRemoteClientBase::ContinueLock::~ContinueLock() {
294 if (m_acquired)
295 unlock();
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000296}
297
Kate Stoneb9c1b512016-09-06 20:57:50 +0000298void GDBRemoteClientBase::ContinueLock::unlock() {
299 lldbassert(m_acquired);
300 {
301 std::unique_lock<std::mutex> lock(m_comm.m_mutex);
302 m_comm.m_is_running = false;
303 }
304 m_comm.m_cv.notify_all();
305 m_acquired = false;
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000306}
307
308GDBRemoteClientBase::ContinueLock::LockResult
Kate Stoneb9c1b512016-09-06 20:57:50 +0000309GDBRemoteClientBase::ContinueLock::lock() {
310 Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
311 if (log)
312 log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
313 __FUNCTION__, m_comm.m_continue_packet.c_str());
314
315 lldbassert(!m_acquired);
316 std::unique_lock<std::mutex> lock(m_comm.m_mutex);
317 m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; });
318 if (m_comm.m_should_stop) {
319 m_comm.m_should_stop = false;
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000320 if (log)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000321 log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled",
322 __FUNCTION__);
323 return LockResult::Cancelled;
324 }
325 if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) !=
326 PacketResult::Success)
327 return LockResult::Failed;
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000328
Kate Stoneb9c1b512016-09-06 20:57:50 +0000329 lldbassert(!m_comm.m_is_running);
330 m_comm.m_is_running = true;
331 m_acquired = true;
332 return LockResult::Success;
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000333}
334
335///////////////////////////////
336// GDBRemoteClientBase::Lock //
337///////////////////////////////
338
339GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340 : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
341 m_acquired(false), m_did_interrupt(false) {
342 SyncWithContinueThread(interrupt);
343 if (m_acquired)
344 m_async_lock.lock();
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000345}
346
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
348 Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
349 std::unique_lock<std::mutex> lock(m_comm.m_mutex);
350 if (m_comm.m_is_running && !interrupt)
351 return; // We were asked to avoid interrupting the sender. Lock is not
352 // acquired.
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000353
Kate Stoneb9c1b512016-09-06 20:57:50 +0000354 ++m_comm.m_async_count;
355 if (m_comm.m_is_running) {
356 if (m_comm.m_async_count == 1) {
357 // The sender has sent the continue packet and we are the first async
358 // packet. Let's interrupt it.
359 const char ctrl_c = '\x03';
360 ConnectionStatus status = eConnectionStatusSuccess;
361 size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL);
362 if (bytes_written == 0) {
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000363 --m_comm.m_async_count;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000364 if (log)
365 log->Printf("GDBRemoteClientBase::Lock::Lock failed to send "
366 "interrupt packet");
367 return;
368 }
369 if (log)
370 log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
371 m_comm.m_interrupt_time = std::chrono::steady_clock::now();
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000372 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000373 m_comm.m_cv.wait(lock, [this] { return m_comm.m_is_running == false; });
374 m_did_interrupt = true;
375 }
376 m_acquired = true;
377}
378
379GDBRemoteClientBase::Lock::~Lock() {
380 if (!m_acquired)
381 return;
382 {
383 std::unique_lock<std::mutex> lock(m_comm.m_mutex);
384 --m_comm.m_async_count;
385 }
386 m_comm.m_cv.notify_one();
Pavel Labath8c1b6bd2016-08-09 12:04:46 +0000387}