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