xref: /freebsd/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1 //===-- GDBRemoteClientBase.cpp -------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "GDBRemoteClientBase.h"
10 
11 #include "llvm/ADT/StringExtras.h"
12 
13 #include "lldb/Target/UnixSignals.h"
14 #include "lldb/Utility/LLDBAssert.h"
15 
16 #include "ProcessGDBRemoteLog.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 using namespace lldb_private::process_gdb_remote;
21 using namespace std::chrono;
22 
23 // When we've sent a continue packet and are waiting for the target to stop,
24 // we wake up the wait with this interval to make sure the stub hasn't gone
25 // away while we were waiting.
26 static const seconds kWakeupInterval(5);
27 
28 /////////////////////////
29 // GDBRemoteClientBase //
30 /////////////////////////
31 
32 GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default;
33 
GDBRemoteClientBase(const char * comm_name)34 GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name)
35     : GDBRemoteCommunication(), Broadcaster(nullptr, comm_name),
36       m_async_count(0), m_is_running(false), m_should_stop(false) {}
37 
SendContinuePacketAndWaitForResponse(ContinueDelegate & delegate,const UnixSignals & signals,llvm::StringRef payload,std::chrono::seconds interrupt_timeout,StringExtractorGDBRemote & response)38 StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
39     ContinueDelegate &delegate, const UnixSignals &signals,
40     llvm::StringRef payload, std::chrono::seconds interrupt_timeout,
41     StringExtractorGDBRemote &response) {
42   Log *log = GetLog(GDBRLog::Process);
43   response.Clear();
44 
45   {
46     std::lock_guard<std::mutex> lock(m_mutex);
47     m_continue_packet = std::string(payload);
48     m_should_stop = false;
49   }
50   ContinueLock cont_lock(*this);
51   if (!cont_lock)
52     return eStateInvalid;
53   OnRunPacketSent(true);
54   // The main ReadPacket loop wakes up at computed_timeout intervals, just to
55   // check that the connection hasn't dropped.  When we wake up we also check
56   // whether there is an interrupt request that has reached its endpoint.
57   // If we want a shorter interrupt timeout that kWakeupInterval, we need to
58   // choose the shorter interval for the wake up as well.
59   std::chrono::seconds computed_timeout = std::min(interrupt_timeout,
60                                                    kWakeupInterval);
61   for (;;) {
62     PacketResult read_result = ReadPacket(response, computed_timeout, false);
63     // Reset the computed_timeout to the default value in case we are going
64     // round again.
65     computed_timeout = std::min(interrupt_timeout, kWakeupInterval);
66     switch (read_result) {
67     case PacketResult::ErrorReplyTimeout: {
68       std::lock_guard<std::mutex> lock(m_mutex);
69       if (m_async_count == 0) {
70         continue;
71       }
72       auto cur_time = steady_clock::now();
73       if (cur_time >= m_interrupt_endpoint)
74         return eStateInvalid;
75       else {
76         // We woke up and found an interrupt is in flight, but we haven't
77         // exceeded the interrupt wait time.  So reset the wait time to the
78         // time left till the interrupt timeout.  But don't wait longer
79         // than our wakeup timeout.
80         auto new_wait = m_interrupt_endpoint - cur_time;
81         computed_timeout = std::min(kWakeupInterval,
82             std::chrono::duration_cast<std::chrono::seconds>(new_wait));
83         continue;
84       }
85       break;
86     }
87     case PacketResult::Success:
88       break;
89     default:
90       LLDB_LOGF(log, "GDBRemoteClientBase::%s () ReadPacket(...) => false",
91                 __FUNCTION__);
92       return eStateInvalid;
93     }
94     if (response.Empty())
95       return eStateInvalid;
96 
97     const char stop_type = response.GetChar();
98     LLDB_LOGF(log, "GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
99               response.GetStringRef().data());
100 
101     switch (stop_type) {
102     case 'W':
103     case 'X':
104       return eStateExited;
105     case 'E':
106       // ERROR
107       return eStateInvalid;
108     default:
109       LLDB_LOGF(log, "GDBRemoteClientBase::%s () unrecognized async packet",
110                 __FUNCTION__);
111       return eStateInvalid;
112     case 'O': {
113       std::string inferior_stdout;
114       response.GetHexByteString(inferior_stdout);
115       delegate.HandleAsyncStdout(inferior_stdout);
116       break;
117     }
118     case 'A':
119       delegate.HandleAsyncMisc(
120           llvm::StringRef(response.GetStringRef()).substr(1));
121       break;
122     case 'J':
123       delegate.HandleAsyncStructuredDataPacket(response.GetStringRef());
124       break;
125     case 'T':
126     case 'S':
127       // Do this with the continue lock held.
128       const bool should_stop = ShouldStop(signals, response);
129       response.SetFilePos(0);
130 
131       // The packet we should resume with. In the future we should check our
132       // thread list and "do the right thing" for new threads that show up
133       // while we stop and run async packets. Setting the packet to 'c' to
134       // continue all threads is the right thing to do 99.99% of the time
135       // because if a thread was single stepping, and we sent an interrupt, we
136       // will notice above that we didn't stop due to an interrupt but stopped
137       // due to stepping and we would _not_ continue. This packet may get
138       // modified by the async actions (e.g. to send a signal).
139       m_continue_packet = 'c';
140       cont_lock.unlock();
141 
142       delegate.HandleStopReply();
143       if (should_stop)
144         return eStateStopped;
145 
146       switch (cont_lock.lock()) {
147       case ContinueLock::LockResult::Success:
148         break;
149       case ContinueLock::LockResult::Failed:
150         return eStateInvalid;
151       case ContinueLock::LockResult::Cancelled:
152         return eStateStopped;
153       }
154       OnRunPacketSent(false);
155       break;
156     }
157   }
158 }
159 
SendAsyncSignal(int signo,std::chrono::seconds interrupt_timeout)160 bool GDBRemoteClientBase::SendAsyncSignal(
161     int signo, std::chrono::seconds interrupt_timeout) {
162   Lock lock(*this, interrupt_timeout);
163   if (!lock || !lock.DidInterrupt())
164     return false;
165 
166   m_continue_packet = 'C';
167   m_continue_packet += llvm::hexdigit((signo / 16) % 16);
168   m_continue_packet += llvm::hexdigit(signo % 16);
169   return true;
170 }
171 
Interrupt(std::chrono::seconds interrupt_timeout)172 bool GDBRemoteClientBase::Interrupt(std::chrono::seconds interrupt_timeout) {
173   Lock lock(*this, interrupt_timeout);
174   if (!lock.DidInterrupt())
175     return false;
176   m_should_stop = true;
177   return true;
178 }
179 
180 GDBRemoteCommunication::PacketResult
SendPacketAndWaitForResponse(llvm::StringRef payload,StringExtractorGDBRemote & response,std::chrono::seconds interrupt_timeout)181 GDBRemoteClientBase::SendPacketAndWaitForResponse(
182     llvm::StringRef payload, StringExtractorGDBRemote &response,
183     std::chrono::seconds interrupt_timeout) {
184   Lock lock(*this, interrupt_timeout);
185   if (!lock) {
186     if (Log *log = GetLog(GDBRLog::Process))
187       LLDB_LOGF(log,
188                 "GDBRemoteClientBase::%s failed to get mutex, not sending "
189                 "packet '%.*s'",
190                 __FUNCTION__, int(payload.size()), payload.data());
191     return PacketResult::ErrorSendFailed;
192   }
193 
194   return SendPacketAndWaitForResponseNoLock(payload, response);
195 }
196 
197 GDBRemoteCommunication::PacketResult
ReadPacketWithOutputSupport(StringExtractorGDBRemote & response,Timeout<std::micro> timeout,bool sync_on_timeout,llvm::function_ref<void (llvm::StringRef)> output_callback)198 GDBRemoteClientBase::ReadPacketWithOutputSupport(
199     StringExtractorGDBRemote &response, Timeout<std::micro> timeout,
200     bool sync_on_timeout,
201     llvm::function_ref<void(llvm::StringRef)> output_callback) {
202   auto result = ReadPacket(response, timeout, sync_on_timeout);
203   while (result == PacketResult::Success && response.IsNormalResponse() &&
204          response.PeekChar() == 'O') {
205     response.GetChar();
206     std::string output;
207     if (response.GetHexByteString(output))
208       output_callback(output);
209     result = ReadPacket(response, timeout, sync_on_timeout);
210   }
211   return result;
212 }
213 
214 GDBRemoteCommunication::PacketResult
SendPacketAndReceiveResponseWithOutputSupport(llvm::StringRef payload,StringExtractorGDBRemote & response,std::chrono::seconds interrupt_timeout,llvm::function_ref<void (llvm::StringRef)> output_callback)215 GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
216     llvm::StringRef payload, StringExtractorGDBRemote &response,
217     std::chrono::seconds interrupt_timeout,
218     llvm::function_ref<void(llvm::StringRef)> output_callback) {
219   Lock lock(*this, interrupt_timeout);
220   if (!lock) {
221     if (Log *log = GetLog(GDBRLog::Process))
222       LLDB_LOGF(log,
223                 "GDBRemoteClientBase::%s failed to get mutex, not sending "
224                 "packet '%.*s'",
225                 __FUNCTION__, int(payload.size()), payload.data());
226     return PacketResult::ErrorSendFailed;
227   }
228 
229   PacketResult packet_result = SendPacketNoLock(payload);
230   if (packet_result != PacketResult::Success)
231     return packet_result;
232 
233   return ReadPacketWithOutputSupport(response, GetPacketTimeout(), true,
234                                      output_callback);
235 }
236 
237 GDBRemoteCommunication::PacketResult
SendPacketAndWaitForResponseNoLock(llvm::StringRef payload,StringExtractorGDBRemote & response)238 GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
239     llvm::StringRef payload, StringExtractorGDBRemote &response) {
240   PacketResult packet_result = SendPacketNoLock(payload);
241   if (packet_result != PacketResult::Success)
242     return packet_result;
243 
244   const size_t max_response_retries = 3;
245   for (size_t i = 0; i < max_response_retries; ++i) {
246     packet_result = ReadPacket(response, GetPacketTimeout(), true);
247     // Make sure we received a response
248     if (packet_result != PacketResult::Success)
249       return packet_result;
250     // Make sure our response is valid for the payload that was sent
251     if (response.ValidateResponse())
252       return packet_result;
253     // Response says it wasn't valid
254     Log *log = GetLog(GDBRLog::Packets);
255     LLDB_LOGF(
256         log,
257         "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
258         int(payload.size()), payload.data(), response.GetStringRef().data(),
259         (i == (max_response_retries - 1))
260             ? "using invalid response and giving up"
261             : "ignoring response and waiting for another");
262   }
263   return packet_result;
264 }
265 
ShouldStop(const UnixSignals & signals,StringExtractorGDBRemote & response)266 bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
267                                      StringExtractorGDBRemote &response) {
268   std::lock_guard<std::mutex> lock(m_mutex);
269 
270   if (m_async_count == 0)
271     return true; // We were not interrupted. The process stopped on its own.
272 
273   // Older debugserver stubs (before April 2016) can return two stop-reply
274   // packets in response to a ^C packet. Additionally, all debugservers still
275   // return two stop replies if the inferior stops due to some other reason
276   // before the remote stub manages to interrupt it. We need to wait for this
277   // additional packet to make sure the packet sequence does not get skewed.
278   StringExtractorGDBRemote extra_stop_reply_packet;
279   ReadPacket(extra_stop_reply_packet, milliseconds(100), false);
280 
281   // Interrupting is typically done using SIGSTOP or SIGINT, so if the process
282   // stops with some other signal, we definitely want to stop.
283   const uint8_t signo = response.GetHexU8(UINT8_MAX);
284   if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
285       signo != signals.GetSignalNumberFromName("SIGINT"))
286     return true;
287 
288   // We probably only stopped to perform some async processing, so continue
289   // after that is done.
290   // TODO: This is not 100% correct, as the process may have been stopped with
291   // SIGINT or SIGSTOP that was not caused by us (e.g. raise(SIGINT)). This will
292   // normally cause a stop, but if it's done concurrently with a async
293   // interrupt, that stop will get eaten (llvm.org/pr20231).
294   return false;
295 }
296 
OnRunPacketSent(bool first)297 void GDBRemoteClientBase::OnRunPacketSent(bool first) {
298   if (first)
299     BroadcastEvent(eBroadcastBitRunPacketSent, nullptr);
300 }
301 
302 ///////////////////////////////////////
303 // GDBRemoteClientBase::ContinueLock //
304 ///////////////////////////////////////
305 
ContinueLock(GDBRemoteClientBase & comm)306 GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm)
307     : m_comm(comm), m_acquired(false) {
308   lock();
309 }
310 
~ContinueLock()311 GDBRemoteClientBase::ContinueLock::~ContinueLock() {
312   if (m_acquired)
313     unlock();
314 }
315 
unlock()316 void GDBRemoteClientBase::ContinueLock::unlock() {
317   lldbassert(m_acquired);
318   {
319     std::unique_lock<std::mutex> lock(m_comm.m_mutex);
320     m_comm.m_is_running = false;
321   }
322   m_comm.m_cv.notify_all();
323   m_acquired = false;
324 }
325 
326 GDBRemoteClientBase::ContinueLock::LockResult
lock()327 GDBRemoteClientBase::ContinueLock::lock() {
328   Log *log = GetLog(GDBRLog::Process);
329   LLDB_LOGF(log, "GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
330             __FUNCTION__, m_comm.m_continue_packet.c_str());
331 
332   lldbassert(!m_acquired);
333   std::unique_lock<std::mutex> lock(m_comm.m_mutex);
334   m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; });
335   if (m_comm.m_should_stop) {
336     m_comm.m_should_stop = false;
337     LLDB_LOGF(log, "GDBRemoteClientBase::ContinueLock::%s() cancelled",
338               __FUNCTION__);
339     return LockResult::Cancelled;
340   }
341   if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) !=
342       PacketResult::Success)
343     return LockResult::Failed;
344 
345   lldbassert(!m_comm.m_is_running);
346   m_comm.m_is_running = true;
347   m_acquired = true;
348   return LockResult::Success;
349 }
350 
351 ///////////////////////////////
352 // GDBRemoteClientBase::Lock //
353 ///////////////////////////////
354 
Lock(GDBRemoteClientBase & comm,std::chrono::seconds interrupt_timeout)355 GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm,
356                                 std::chrono::seconds interrupt_timeout)
357     : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
358       m_interrupt_timeout(interrupt_timeout), m_acquired(false),
359       m_did_interrupt(false) {
360   SyncWithContinueThread();
361   if (m_acquired)
362     m_async_lock.lock();
363 }
364 
SyncWithContinueThread()365 void GDBRemoteClientBase::Lock::SyncWithContinueThread() {
366   Log *log = GetLog(GDBRLog::Process|GDBRLog::Packets);
367   std::unique_lock<std::mutex> lock(m_comm.m_mutex);
368   if (m_comm.m_is_running && m_interrupt_timeout == std::chrono::seconds(0))
369     return; // We were asked to avoid interrupting the sender. Lock is not
370             // acquired.
371 
372   ++m_comm.m_async_count;
373   if (m_comm.m_is_running) {
374     if (m_comm.m_async_count == 1) {
375       // The sender has sent the continue packet and we are the first async
376       // packet. Let's interrupt it.
377       const char ctrl_c = '\x03';
378       ConnectionStatus status = eConnectionStatusSuccess;
379       size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, nullptr);
380       if (bytes_written == 0) {
381         --m_comm.m_async_count;
382         LLDB_LOGF(log, "GDBRemoteClientBase::Lock::Lock failed to send "
383                        "interrupt packet");
384         return;
385       }
386       m_comm.m_interrupt_endpoint = steady_clock::now() + m_interrupt_timeout;
387       if (log)
388         log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
389     }
390     m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });
391     m_did_interrupt = true;
392   }
393   m_acquired = true;
394 }
395 
~Lock()396 GDBRemoteClientBase::Lock::~Lock() {
397   if (!m_acquired)
398     return;
399   {
400     std::unique_lock<std::mutex> lock(m_comm.m_mutex);
401     --m_comm.m_async_count;
402   }
403   m_comm.m_cv.notify_one();
404 }
405