xref: /llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp (revision fcdb1af655a80b4f1b4f17929235613216ebaaf5)
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 =
192         ReadPacket(response, GetPacketTimeoutInMicroSeconds(), true);
193     // Make sure we received a response
194     if (packet_result != PacketResult::Success)
195       return packet_result;
196     // Make sure our response is valid for the payload that was sent
197     if (response.ValidateResponse())
198       return packet_result;
199     // Response says it wasn't valid
200     Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS);
201     if (log)
202       log->Printf(
203           "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
204           int(payload.size()), payload.data(), response.GetStringRef().c_str(),
205           (i == (max_response_retries - 1))
206               ? "using invalid response and giving up"
207               : "ignoring response and waiting for another");
208   }
209   return packet_result;
210 }
211 
212 bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload,
213                                           StringExtractorGDBRemote &response) {
214   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
215   if (log)
216     log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
217 
218   // we want to lock down packet sending while we continue
219   Lock lock(*this, true);
220 
221   if (log)
222     log->Printf(
223         "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s",
224         __FUNCTION__, int(payload.size()), payload.data());
225 
226   if (SendPacketNoLock(payload) != PacketResult::Success)
227     return false;
228 
229   OnRunPacketSent(true);
230 
231   // wait for the response to the vCont
232   if (ReadPacket(response, UINT32_MAX, false) == PacketResult::Success) {
233     if (response.IsOKResponse())
234       return true;
235   }
236 
237   return false;
238 }
239 bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
240                                      StringExtractorGDBRemote &response) {
241   std::lock_guard<std::mutex> lock(m_mutex);
242 
243   if (m_async_count == 0)
244     return true; // We were not interrupted. The process stopped on its own.
245 
246   // Older debugserver stubs (before April 2016) can return two
247   // stop-reply packets in response to a ^C packet.
248   // Additionally, all debugservers still return two stop replies if
249   // the inferior stops due to some other reason before the remote
250   // stub manages to interrupt it. We need to wait for this
251   // additional packet to make sure the packet sequence does not get
252   // skewed.
253   StringExtractorGDBRemote extra_stop_reply_packet;
254   uint32_t timeout_usec = 100000; // 100ms
255   ReadPacket(extra_stop_reply_packet, timeout_usec, false);
256 
257   // Interrupting is typically done using SIGSTOP or SIGINT, so if
258   // the process stops with some other signal, we definitely want to
259   // stop.
260   const uint8_t signo = response.GetHexU8(UINT8_MAX);
261   if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
262       signo != signals.GetSignalNumberFromName("SIGINT"))
263     return true;
264 
265   // We probably only stopped to perform some async processing, so continue
266   // after that is done.
267   // TODO: This is not 100% correct, as the process may have been stopped with
268   // SIGINT or SIGSTOP
269   // that was not caused by us (e.g. raise(SIGINT)). This will normally cause a
270   // stop, but if it's
271   // done concurrently with a async interrupt, that stop will get eaten
272   // (llvm.org/pr20231).
273   return false;
274 }
275 
276 void GDBRemoteClientBase::OnRunPacketSent(bool first) {
277   if (first)
278     BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
279 }
280 
281 ///////////////////////////////////////
282 // GDBRemoteClientBase::ContinueLock //
283 ///////////////////////////////////////
284 
285 GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm)
286     : m_comm(comm), m_acquired(false) {
287   lock();
288 }
289 
290 GDBRemoteClientBase::ContinueLock::~ContinueLock() {
291   if (m_acquired)
292     unlock();
293 }
294 
295 void GDBRemoteClientBase::ContinueLock::unlock() {
296   lldbassert(m_acquired);
297   {
298     std::unique_lock<std::mutex> lock(m_comm.m_mutex);
299     m_comm.m_is_running = false;
300   }
301   m_comm.m_cv.notify_all();
302   m_acquired = false;
303 }
304 
305 GDBRemoteClientBase::ContinueLock::LockResult
306 GDBRemoteClientBase::ContinueLock::lock() {
307   Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
308   if (log)
309     log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
310                 __FUNCTION__, m_comm.m_continue_packet.c_str());
311 
312   lldbassert(!m_acquired);
313   std::unique_lock<std::mutex> lock(m_comm.m_mutex);
314   m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; });
315   if (m_comm.m_should_stop) {
316     m_comm.m_should_stop = false;
317     if (log)
318       log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled",
319                   __FUNCTION__);
320     return LockResult::Cancelled;
321   }
322   if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) !=
323       PacketResult::Success)
324     return LockResult::Failed;
325 
326   lldbassert(!m_comm.m_is_running);
327   m_comm.m_is_running = true;
328   m_acquired = true;
329   return LockResult::Success;
330 }
331 
332 ///////////////////////////////
333 // GDBRemoteClientBase::Lock //
334 ///////////////////////////////
335 
336 GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
337     : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
338       m_acquired(false), m_did_interrupt(false) {
339   SyncWithContinueThread(interrupt);
340   if (m_acquired)
341     m_async_lock.lock();
342 }
343 
344 void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
345   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
346   std::unique_lock<std::mutex> lock(m_comm.m_mutex);
347   if (m_comm.m_is_running && !interrupt)
348     return; // We were asked to avoid interrupting the sender. Lock is not
349             // acquired.
350 
351   ++m_comm.m_async_count;
352   if (m_comm.m_is_running) {
353     if (m_comm.m_async_count == 1) {
354       // The sender has sent the continue packet and we are the first async
355       // packet. Let's interrupt it.
356       const char ctrl_c = '\x03';
357       ConnectionStatus status = eConnectionStatusSuccess;
358       size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL);
359       if (bytes_written == 0) {
360         --m_comm.m_async_count;
361         if (log)
362           log->Printf("GDBRemoteClientBase::Lock::Lock failed to send "
363                       "interrupt packet");
364         return;
365       }
366       if (log)
367         log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
368       m_comm.m_interrupt_time = std::chrono::steady_clock::now();
369     }
370     m_comm.m_cv.wait(lock, [this] { return m_comm.m_is_running == false; });
371     m_did_interrupt = true;
372   }
373   m_acquired = true;
374 }
375 
376 GDBRemoteClientBase::Lock::~Lock() {
377   if (!m_acquired)
378     return;
379   {
380     std::unique_lock<std::mutex> lock(m_comm.m_mutex);
381     --m_comm.m_async_count;
382   }
383   m_comm.m_cv.notify_one();
384 }
385