xref: /llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp (revision 0faf37333c8bf7eaca3500c7d79c7fb99112caa5)
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, const char *listener_name)
33     : GDBRemoteCommunication(comm_name, listener_name), m_async_count(0), m_is_running(false), m_should_stop(false)
34 {
35 }
36 
37 StateType
38 GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(ContinueDelegate &delegate, const UnixSignals &signals,
39                                                           llvm::StringRef payload, StringExtractorGDBRemote &response)
40 {
41     Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
42     response.Clear();
43 
44     {
45         std::lock_guard<std::mutex> lock(m_mutex);
46         m_continue_packet = payload;
47         m_should_stop = false;
48     }
49     ContinueLock cont_lock(*this);
50     if (!cont_lock)
51         return eStateInvalid;
52     OnRunPacketSent(true);
53 
54     for (;;)
55     {
56         PacketResult read_result = ReadPacket(
57             response, std::chrono::duration_cast<std::chrono::microseconds>(kInterruptTimeout).count(), false);
58         switch (read_result)
59         {
60             case PacketResult::ErrorReplyTimeout:
61             {
62                 std::lock_guard<std::mutex> lock(m_mutex);
63                 if (m_async_count == 0)
64                     continue;
65                 if (std::chrono::steady_clock::now() >= 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", __FUNCTION__);
73                 return eStateInvalid;
74         }
75         if (response.Empty())
76             return eStateInvalid;
77 
78         const char stop_type = response.GetChar();
79         if (log)
80             log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str());
81 
82         switch (stop_type)
83         {
84             case 'W':
85             case 'X':
86                 return eStateExited;
87             case 'E':
88                 // ERROR
89                 return eStateInvalid;
90             default:
91                 if (log)
92                     log->Printf("GDBRemoteClientBase::%s () unrecognized async packet", __FUNCTION__);
93                 return eStateInvalid;
94             case 'O':
95             {
96                 std::string inferior_stdout;
97                 response.GetHexByteString(inferior_stdout);
98                 delegate.HandleAsyncStdout(inferior_stdout);
99                 break;
100             }
101             case 'A':
102                 delegate.HandleAsyncMisc(llvm::StringRef(response.GetStringRef()).substr(1));
103                 break;
104 
105             case 'J':
106                 // Asynchronous JSON packet, destined for a
107                 // StructuredDataPlugin.
108             {
109                 // Parse the content into a StructuredData instance.
110                 auto payload_index = strlen("JSON-async:");
111                 StructuredData::ObjectSP json_sp =
112                     StructuredData::ParseJSON(response.GetStringRef()
113                                               .substr(payload_index));
114                 if (log)
115                 {
116                     if (json_sp)
117                         log->Printf(
118                                     "GDBRemoteCommmunicationClientBase::%s() "
119                                     "received Async StructuredData packet: %s",
120                                     __FUNCTION__,
121                                     response.GetStringRef().
122                                     substr(payload_index).c_str());
123                     else
124                         log->Printf("GDBRemoteCommmunicationClientBase::%s"
125                                     "() received StructuredData packet:"
126                                     " parse failure", __FUNCTION__);
127                 }
128 
129                 // Pass the data to the process to route to the
130                 // appropriate plugin.  The plugin controls what happens
131                 // to it from there.
132                 bool routed = delegate.HandleAsyncStructuredData(json_sp);
133                 if (log)
134                     log->Printf("GDBRemoteCommmunicationClientBase::%s()"
135                                 " packet %s", __FUNCTION__,
136                                 routed ? "handled" : "not handled");
137                 break;
138             }
139             case 'T':
140             case 'S':
141                 // Do this with the continue lock held.
142                 const bool should_stop = ShouldStop(signals, response);
143                 response.SetFilePos(0);
144 
145                 // The packet we should resume with. In the future
146                 // we should check our thread list and "do the right thing"
147                 // for new threads that show up while we stop and run async
148                 // packets. Setting the packet to 'c' to continue all threads
149                 // is the right thing to do 99.99% of the time because if a
150                 // thread was single stepping, and we sent an interrupt, we
151                 // will notice above that we didn't stop due to an interrupt
152                 // but stopped due to stepping and we would _not_ continue.
153                 // This packet may get modified by the async actions (e.g. to send a signal).
154                 m_continue_packet = 'c';
155                 cont_lock.unlock();
156 
157                 delegate.HandleStopReply();
158                 if (should_stop)
159                     return eStateStopped;
160 
161                 switch (cont_lock.lock())
162                 {
163                     case ContinueLock::LockResult::Success:
164                         break;
165                     case ContinueLock::LockResult::Failed:
166                         return eStateInvalid;
167                     case ContinueLock::LockResult::Cancelled:
168                         return eStateStopped;
169                 }
170                 OnRunPacketSent(false);
171                 break;
172         }
173     }
174 }
175 
176 bool
177 GDBRemoteClientBase::SendAsyncSignal(int signo)
178 {
179     Lock lock(*this, true);
180     if (!lock || !lock.DidInterrupt())
181         return false;
182 
183     m_continue_packet = 'C';
184     m_continue_packet += llvm::hexdigit((signo / 16) % 16);
185     m_continue_packet += llvm::hexdigit(signo % 16);
186     return true;
187 }
188 
189 bool
190 GDBRemoteClientBase::Interrupt()
191 {
192     Lock lock(*this, true);
193     if (!lock.DidInterrupt())
194         return false;
195     m_should_stop = true;
196     return true;
197 }
198 GDBRemoteCommunication::PacketResult
199 GDBRemoteClientBase::SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response,
200                                                   bool send_async)
201 {
202     Lock lock(*this, send_async);
203     if (!lock)
204     {
205         if (Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
206             log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending packet '%.*s' (send_async=%d)",
207                         __FUNCTION__, int(payload.size()), payload.data(), send_async);
208         return PacketResult::ErrorSendFailed;
209     }
210 
211     return SendPacketAndWaitForResponse(payload, response, lock);
212 }
213 
214 GDBRemoteCommunication::PacketResult
215 GDBRemoteClientBase::SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response,
216                                                   const Lock &lock)
217 {
218     assert(lock);
219     PacketResult packet_result = SendPacketNoLock(payload.data(), payload.size());
220     if (packet_result != PacketResult::Success)
221         return packet_result;
222 
223     const size_t max_response_retries = 3;
224     for (size_t i = 0; i < max_response_retries; ++i)
225     {
226         packet_result = ReadPacket(response, GetPacketTimeoutInMicroSeconds(), true);
227         // Make sure we received a response
228         if (packet_result != PacketResult::Success)
229             return packet_result;
230         // Make sure our response is valid for the payload that was sent
231         if (response.ValidateResponse())
232             return packet_result;
233         // Response says it wasn't valid
234         Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS);
235         if (log)
236             log->Printf("error: packet with payload \"%.*s\" got invalid response \"%s\": %s", int(payload.size()),
237                         payload.data(), response.GetStringRef().c_str(),
238                         (i == (max_response_retries - 1)) ? "using invalid response and giving up"
239                                                           : "ignoring response and waiting for another");
240     }
241     return packet_result;
242 }
243 
244 bool
245 GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload, StringExtractorGDBRemote &response)
246 {
247     Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
248     if (log)
249         log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
250 
251     // we want to lock down packet sending while we continue
252     Lock lock(*this, true);
253 
254     if (log)
255         log->Printf("GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s", __FUNCTION__, int(payload.size()),
256                     payload.data());
257 
258     if (SendPacketNoLock(payload.data(), payload.size()) != PacketResult::Success)
259         return false;
260 
261     OnRunPacketSent(true);
262 
263     // wait for the response to the vCont
264     if (ReadPacket(response, UINT32_MAX, false) == PacketResult::Success)
265     {
266         if (response.IsOKResponse())
267             return true;
268     }
269 
270     return false;
271 }
272 bool
273 GDBRemoteClientBase::ShouldStop(const UnixSignals &signals, StringExtractorGDBRemote &response)
274 {
275     std::lock_guard<std::mutex> lock(m_mutex);
276 
277     if (m_async_count == 0)
278         return true; // We were not interrupted. The process stopped on its own.
279 
280     // Older debugserver stubs (before April 2016) can return two
281     // stop-reply packets in response to a ^C packet.
282     // Additionally, all debugservers still return two stop replies if
283     // the inferior stops due to some other reason before the remote
284     // stub manages to interrupt it. We need to wait for this
285     // additional packet to make sure the packet sequence does not get
286     // skewed.
287     StringExtractorGDBRemote extra_stop_reply_packet;
288     uint32_t timeout_usec = 100000; // 100ms
289     ReadPacket(extra_stop_reply_packet, timeout_usec, false);
290 
291     // Interrupting is typically done using SIGSTOP or SIGINT, so if
292     // the process stops with some other signal, we definitely want to
293     // stop.
294     const uint8_t signo = response.GetHexU8(UINT8_MAX);
295     if (signo != signals.GetSignalNumberFromName("SIGSTOP") && signo != signals.GetSignalNumberFromName("SIGINT"))
296         return true;
297 
298     // We probably only stopped to perform some async processing, so continue after that is done.
299     // TODO: This is not 100% correct, as the process may have been stopped with SIGINT or SIGSTOP
300     // that was not caused by us (e.g. raise(SIGINT)). This will normally cause a stop, but if it's
301     // done concurrently with a async interrupt, that stop will get eaten (llvm.org/pr20231).
302     return false;
303 }
304 
305 void
306 GDBRemoteClientBase::OnRunPacketSent(bool first)
307 {
308     if (first)
309         BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
310 }
311 
312 ///////////////////////////////////////
313 // GDBRemoteClientBase::ContinueLock //
314 ///////////////////////////////////////
315 
316 GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm) : m_comm(comm), m_acquired(false)
317 {
318     lock();
319 }
320 
321 GDBRemoteClientBase::ContinueLock::~ContinueLock()
322 {
323     if (m_acquired)
324         unlock();
325 }
326 
327 void
328 GDBRemoteClientBase::ContinueLock::unlock()
329 {
330     lldbassert(m_acquired);
331     {
332         std::unique_lock<std::mutex> lock(m_comm.m_mutex);
333         m_comm.m_is_running = false;
334     }
335     m_comm.m_cv.notify_all();
336     m_acquired = false;
337 }
338 
339 GDBRemoteClientBase::ContinueLock::LockResult
340 GDBRemoteClientBase::ContinueLock::lock()
341 {
342     Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
343     if (log)
344         log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s", __FUNCTION__,
345                     m_comm.m_continue_packet.c_str());
346 
347     lldbassert(!m_acquired);
348     std::unique_lock<std::mutex> lock(m_comm.m_mutex);
349     m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; });
350     if (m_comm.m_should_stop)
351     {
352         m_comm.m_should_stop = false;
353         if (log)
354             log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled", __FUNCTION__);
355         return LockResult::Cancelled;
356     }
357     if (m_comm.SendPacketNoLock(m_comm.m_continue_packet.data(), m_comm.m_continue_packet.size()) !=
358         PacketResult::Success)
359         return LockResult::Failed;
360 
361     lldbassert(!m_comm.m_is_running);
362     m_comm.m_is_running = true;
363     m_acquired = true;
364     return LockResult::Success;
365 }
366 
367 ///////////////////////////////
368 // GDBRemoteClientBase::Lock //
369 ///////////////////////////////
370 
371 GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
372     : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm), m_acquired(false), m_did_interrupt(false)
373 {
374     SyncWithContinueThread(interrupt);
375     if (m_acquired)
376         m_async_lock.lock();
377 }
378 
379 void
380 GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt)
381 {
382     Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
383     std::unique_lock<std::mutex> lock(m_comm.m_mutex);
384     if (m_comm.m_is_running && !interrupt)
385         return; // We were asked to avoid interrupting the sender. Lock is not acquired.
386 
387     ++m_comm.m_async_count;
388     if (m_comm.m_is_running)
389     {
390         if (m_comm.m_async_count == 1)
391         {
392             // The sender has sent the continue packet and we are the first async packet. Let's interrupt it.
393             const char ctrl_c = '\x03';
394             ConnectionStatus status = eConnectionStatusSuccess;
395             size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL);
396             if (bytes_written == 0)
397             {
398                 --m_comm.m_async_count;
399                 if (log)
400                     log->Printf("GDBRemoteClientBase::Lock::Lock failed to send interrupt packet");
401                 return;
402             }
403             if (log)
404                 log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
405             m_comm.m_interrupt_time = std::chrono::steady_clock::now();
406         }
407         m_comm.m_cv.wait(lock, [this] { return m_comm.m_is_running == false; });
408         m_did_interrupt = true;
409     }
410     m_acquired = true;
411 }
412 
413 GDBRemoteClientBase::Lock::~Lock()
414 {
415     if (!m_acquired)
416         return;
417     {
418         std::unique_lock<std::mutex> lock(m_comm.m_mutex);
419         --m_comm.m_async_count;
420     }
421     m_comm.m_cv.notify_one();
422 }
423