xref: /llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp (revision 3aa049102fd0e80600622b29fde5c973b6138cf4)
1 //===-- 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 
14 #include "lldb/Target/Process.h"
15 #include "lldb/Target/UnixSignals.h"
16 #include "lldb/Utility/LLDBAssert.h"
17 
18 #include "ProcessGDBRemoteLog.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 using namespace lldb_private::process_gdb_remote;
23 
24 static const std::chrono::seconds kInterruptTimeout(5);
25 
26 /////////////////////////
27 // GDBRemoteClientBase //
28 /////////////////////////
29 
30 GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default;
31 
32 GDBRemoteClientBase::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) {}
36 
37 StateType 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();
42 
43   {
44     std::lock_guard<std::mutex> lock(m_mutex);
45     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);
52 
53   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;
78 
79     const char stop_type = response.GetChar();
80     if (log)
81       log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
82                   response.GetStringRef().c_str());
83 
84     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;
106     case 'J':
107       delegate.HandleAsyncStructuredDataPacket(response.GetStringRef());
108       break;
109     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   }
144 }
145 
146 bool 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 
157 bool GDBRemoteClientBase::Interrupt() {
158   Lock lock(*this, true);
159   if (!lock.DidInterrupt())
160     return false;
161   m_should_stop = true;
162   return true;
163 }
164 GDBRemoteCommunication::PacketResult
165 GDBRemoteClientBase::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 
182 GDBRemoteCommunication::PacketResult
183 GDBRemoteClientBase::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) {
191     packet_result = ReadPacket(
192         response, std::chrono::duration_cast<std::chrono::microseconds>(
193                       GetPacketTimeout())
194                       .count(),
195         true);
196     // 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 
215 bool 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 }
242 bool 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 
279 void GDBRemoteClientBase::OnRunPacketSent(bool first) {
280   if (first)
281     BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
282 }
283 
284 ///////////////////////////////////////
285 // GDBRemoteClientBase::ContinueLock //
286 ///////////////////////////////////////
287 
288 GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm)
289     : m_comm(comm), m_acquired(false) {
290   lock();
291 }
292 
293 GDBRemoteClientBase::ContinueLock::~ContinueLock() {
294   if (m_acquired)
295     unlock();
296 }
297 
298 void 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;
306 }
307 
308 GDBRemoteClientBase::ContinueLock::LockResult
309 GDBRemoteClientBase::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;
320     if (log)
321       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;
328 
329   lldbassert(!m_comm.m_is_running);
330   m_comm.m_is_running = true;
331   m_acquired = true;
332   return LockResult::Success;
333 }
334 
335 ///////////////////////////////
336 // GDBRemoteClientBase::Lock //
337 ///////////////////////////////
338 
339 GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
340     : 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();
345 }
346 
347 void 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.
353 
354   ++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) {
363         --m_comm.m_async_count;
364         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();
372     }
373     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 
379 GDBRemoteClientBase::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();
387 }
388