xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp (revision dda2819751e49c83612958492e38917049128b41)
1*dda28197Spatrick //===-- GDBRemoteClientBase.cpp -------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "GDBRemoteClientBase.h"
10061da546Spatrick 
11061da546Spatrick #include "llvm/ADT/StringExtras.h"
12061da546Spatrick 
13061da546Spatrick #include "lldb/Target/UnixSignals.h"
14061da546Spatrick #include "lldb/Utility/LLDBAssert.h"
15061da546Spatrick 
16061da546Spatrick #include "ProcessGDBRemoteLog.h"
17061da546Spatrick 
18061da546Spatrick using namespace lldb;
19061da546Spatrick using namespace lldb_private;
20061da546Spatrick using namespace lldb_private::process_gdb_remote;
21061da546Spatrick using namespace std::chrono;
22061da546Spatrick 
23061da546Spatrick static const seconds kInterruptTimeout(5);
24061da546Spatrick 
25061da546Spatrick /////////////////////////
26061da546Spatrick // GDBRemoteClientBase //
27061da546Spatrick /////////////////////////
28061da546Spatrick 
29061da546Spatrick GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default;
30061da546Spatrick 
31061da546Spatrick GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name,
32061da546Spatrick                                          const char *listener_name)
33061da546Spatrick     : GDBRemoteCommunication(comm_name, listener_name), m_async_count(0),
34061da546Spatrick       m_is_running(false), m_should_stop(false) {}
35061da546Spatrick 
36061da546Spatrick StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
37061da546Spatrick     ContinueDelegate &delegate, const UnixSignals &signals,
38061da546Spatrick     llvm::StringRef payload, StringExtractorGDBRemote &response) {
39061da546Spatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
40061da546Spatrick   response.Clear();
41061da546Spatrick 
42061da546Spatrick   {
43061da546Spatrick     std::lock_guard<std::mutex> lock(m_mutex);
44*dda28197Spatrick     m_continue_packet = std::string(payload);
45061da546Spatrick     m_should_stop = false;
46061da546Spatrick   }
47061da546Spatrick   ContinueLock cont_lock(*this);
48061da546Spatrick   if (!cont_lock)
49061da546Spatrick     return eStateInvalid;
50061da546Spatrick   OnRunPacketSent(true);
51061da546Spatrick 
52061da546Spatrick   for (;;) {
53061da546Spatrick     PacketResult read_result = ReadPacket(response, kInterruptTimeout, false);
54061da546Spatrick     switch (read_result) {
55061da546Spatrick     case PacketResult::ErrorReplyTimeout: {
56061da546Spatrick       std::lock_guard<std::mutex> lock(m_mutex);
57061da546Spatrick       if (m_async_count == 0)
58061da546Spatrick         continue;
59061da546Spatrick       if (steady_clock::now() >= m_interrupt_time + kInterruptTimeout)
60061da546Spatrick         return eStateInvalid;
61061da546Spatrick       break;
62061da546Spatrick     }
63061da546Spatrick     case PacketResult::Success:
64061da546Spatrick       break;
65061da546Spatrick     default:
66061da546Spatrick       LLDB_LOGF(log, "GDBRemoteClientBase::%s () ReadPacket(...) => false",
67061da546Spatrick                 __FUNCTION__);
68061da546Spatrick       return eStateInvalid;
69061da546Spatrick     }
70061da546Spatrick     if (response.Empty())
71061da546Spatrick       return eStateInvalid;
72061da546Spatrick 
73061da546Spatrick     const char stop_type = response.GetChar();
74061da546Spatrick     LLDB_LOGF(log, "GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
75061da546Spatrick               response.GetStringRef().data());
76061da546Spatrick 
77061da546Spatrick     switch (stop_type) {
78061da546Spatrick     case 'W':
79061da546Spatrick     case 'X':
80061da546Spatrick       return eStateExited;
81061da546Spatrick     case 'E':
82061da546Spatrick       // ERROR
83061da546Spatrick       return eStateInvalid;
84061da546Spatrick     default:
85061da546Spatrick       LLDB_LOGF(log, "GDBRemoteClientBase::%s () unrecognized async packet",
86061da546Spatrick                 __FUNCTION__);
87061da546Spatrick       return eStateInvalid;
88061da546Spatrick     case 'O': {
89061da546Spatrick       std::string inferior_stdout;
90061da546Spatrick       response.GetHexByteString(inferior_stdout);
91061da546Spatrick       delegate.HandleAsyncStdout(inferior_stdout);
92061da546Spatrick       break;
93061da546Spatrick     }
94061da546Spatrick     case 'A':
95061da546Spatrick       delegate.HandleAsyncMisc(
96061da546Spatrick           llvm::StringRef(response.GetStringRef()).substr(1));
97061da546Spatrick       break;
98061da546Spatrick     case 'J':
99061da546Spatrick       delegate.HandleAsyncStructuredDataPacket(response.GetStringRef());
100061da546Spatrick       break;
101061da546Spatrick     case 'T':
102061da546Spatrick     case 'S':
103061da546Spatrick       // Do this with the continue lock held.
104061da546Spatrick       const bool should_stop = ShouldStop(signals, response);
105061da546Spatrick       response.SetFilePos(0);
106061da546Spatrick 
107061da546Spatrick       // The packet we should resume with. In the future we should check our
108061da546Spatrick       // thread list and "do the right thing" for new threads that show up
109061da546Spatrick       // while we stop and run async packets. Setting the packet to 'c' to
110061da546Spatrick       // continue all threads is the right thing to do 99.99% of the time
111061da546Spatrick       // because if a thread was single stepping, and we sent an interrupt, we
112061da546Spatrick       // will notice above that we didn't stop due to an interrupt but stopped
113061da546Spatrick       // due to stepping and we would _not_ continue. This packet may get
114061da546Spatrick       // modified by the async actions (e.g. to send a signal).
115061da546Spatrick       m_continue_packet = 'c';
116061da546Spatrick       cont_lock.unlock();
117061da546Spatrick 
118061da546Spatrick       delegate.HandleStopReply();
119061da546Spatrick       if (should_stop)
120061da546Spatrick         return eStateStopped;
121061da546Spatrick 
122061da546Spatrick       switch (cont_lock.lock()) {
123061da546Spatrick       case ContinueLock::LockResult::Success:
124061da546Spatrick         break;
125061da546Spatrick       case ContinueLock::LockResult::Failed:
126061da546Spatrick         return eStateInvalid;
127061da546Spatrick       case ContinueLock::LockResult::Cancelled:
128061da546Spatrick         return eStateStopped;
129061da546Spatrick       }
130061da546Spatrick       OnRunPacketSent(false);
131061da546Spatrick       break;
132061da546Spatrick     }
133061da546Spatrick   }
134061da546Spatrick }
135061da546Spatrick 
136061da546Spatrick bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
137061da546Spatrick   Lock lock(*this, true);
138061da546Spatrick   if (!lock || !lock.DidInterrupt())
139061da546Spatrick     return false;
140061da546Spatrick 
141061da546Spatrick   m_continue_packet = 'C';
142061da546Spatrick   m_continue_packet += llvm::hexdigit((signo / 16) % 16);
143061da546Spatrick   m_continue_packet += llvm::hexdigit(signo % 16);
144061da546Spatrick   return true;
145061da546Spatrick }
146061da546Spatrick 
147061da546Spatrick bool GDBRemoteClientBase::Interrupt() {
148061da546Spatrick   Lock lock(*this, true);
149061da546Spatrick   if (!lock.DidInterrupt())
150061da546Spatrick     return false;
151061da546Spatrick   m_should_stop = true;
152061da546Spatrick   return true;
153061da546Spatrick }
154061da546Spatrick GDBRemoteCommunication::PacketResult
155061da546Spatrick GDBRemoteClientBase::SendPacketAndWaitForResponse(
156061da546Spatrick     llvm::StringRef payload, StringExtractorGDBRemote &response,
157061da546Spatrick     bool send_async) {
158061da546Spatrick   Lock lock(*this, send_async);
159061da546Spatrick   if (!lock) {
160061da546Spatrick     if (Log *log =
161061da546Spatrick             ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
162061da546Spatrick       LLDB_LOGF(log,
163061da546Spatrick                 "GDBRemoteClientBase::%s failed to get mutex, not sending "
164061da546Spatrick                 "packet '%.*s' (send_async=%d)",
165061da546Spatrick                 __FUNCTION__, int(payload.size()), payload.data(), send_async);
166061da546Spatrick     return PacketResult::ErrorSendFailed;
167061da546Spatrick   }
168061da546Spatrick 
169061da546Spatrick   return SendPacketAndWaitForResponseNoLock(payload, response);
170061da546Spatrick }
171061da546Spatrick 
172061da546Spatrick GDBRemoteCommunication::PacketResult
173061da546Spatrick GDBRemoteClientBase::SendPacketAndReceiveResponseWithOutputSupport(
174061da546Spatrick     llvm::StringRef payload, StringExtractorGDBRemote &response,
175061da546Spatrick     bool send_async,
176061da546Spatrick     llvm::function_ref<void(llvm::StringRef)> output_callback) {
177061da546Spatrick   Lock lock(*this, send_async);
178061da546Spatrick   if (!lock) {
179061da546Spatrick     if (Log *log =
180061da546Spatrick             ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
181061da546Spatrick       LLDB_LOGF(log,
182061da546Spatrick                 "GDBRemoteClientBase::%s failed to get mutex, not sending "
183061da546Spatrick                 "packet '%.*s' (send_async=%d)",
184061da546Spatrick                 __FUNCTION__, int(payload.size()), payload.data(), send_async);
185061da546Spatrick     return PacketResult::ErrorSendFailed;
186061da546Spatrick   }
187061da546Spatrick 
188061da546Spatrick   PacketResult packet_result = SendPacketNoLock(payload);
189061da546Spatrick   if (packet_result != PacketResult::Success)
190061da546Spatrick     return packet_result;
191061da546Spatrick 
192061da546Spatrick   return ReadPacketWithOutputSupport(response, GetPacketTimeout(), true,
193061da546Spatrick                                      output_callback);
194061da546Spatrick }
195061da546Spatrick 
196061da546Spatrick GDBRemoteCommunication::PacketResult
197061da546Spatrick GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
198061da546Spatrick     llvm::StringRef payload, StringExtractorGDBRemote &response) {
199061da546Spatrick   PacketResult packet_result = SendPacketNoLock(payload);
200061da546Spatrick   if (packet_result != PacketResult::Success)
201061da546Spatrick     return packet_result;
202061da546Spatrick 
203061da546Spatrick   const size_t max_response_retries = 3;
204061da546Spatrick   for (size_t i = 0; i < max_response_retries; ++i) {
205061da546Spatrick     packet_result = ReadPacket(response, GetPacketTimeout(), true);
206061da546Spatrick     // Make sure we received a response
207061da546Spatrick     if (packet_result != PacketResult::Success)
208061da546Spatrick       return packet_result;
209061da546Spatrick     // Make sure our response is valid for the payload that was sent
210061da546Spatrick     if (response.ValidateResponse())
211061da546Spatrick       return packet_result;
212061da546Spatrick     // Response says it wasn't valid
213061da546Spatrick     Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS);
214061da546Spatrick     LLDB_LOGF(
215061da546Spatrick         log,
216061da546Spatrick         "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
217061da546Spatrick         int(payload.size()), payload.data(), response.GetStringRef().data(),
218061da546Spatrick         (i == (max_response_retries - 1))
219061da546Spatrick             ? "using invalid response and giving up"
220061da546Spatrick             : "ignoring response and waiting for another");
221061da546Spatrick   }
222061da546Spatrick   return packet_result;
223061da546Spatrick }
224061da546Spatrick 
225061da546Spatrick bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload,
226061da546Spatrick                                           StringExtractorGDBRemote &response) {
227061da546Spatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
228061da546Spatrick   LLDB_LOGF(log, "GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
229061da546Spatrick 
230061da546Spatrick   // we want to lock down packet sending while we continue
231061da546Spatrick   Lock lock(*this, true);
232061da546Spatrick 
233061da546Spatrick   LLDB_LOGF(log,
234061da546Spatrick             "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s",
235061da546Spatrick             __FUNCTION__, int(payload.size()), payload.data());
236061da546Spatrick 
237061da546Spatrick   if (SendPacketNoLock(payload) != PacketResult::Success)
238061da546Spatrick     return false;
239061da546Spatrick 
240061da546Spatrick   OnRunPacketSent(true);
241061da546Spatrick 
242061da546Spatrick   // wait for the response to the vCont
243061da546Spatrick   if (ReadPacket(response, llvm::None, false) == PacketResult::Success) {
244061da546Spatrick     if (response.IsOKResponse())
245061da546Spatrick       return true;
246061da546Spatrick   }
247061da546Spatrick 
248061da546Spatrick   return false;
249061da546Spatrick }
250061da546Spatrick bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
251061da546Spatrick                                      StringExtractorGDBRemote &response) {
252061da546Spatrick   std::lock_guard<std::mutex> lock(m_mutex);
253061da546Spatrick 
254061da546Spatrick   if (m_async_count == 0)
255061da546Spatrick     return true; // We were not interrupted. The process stopped on its own.
256061da546Spatrick 
257061da546Spatrick   // Older debugserver stubs (before April 2016) can return two stop-reply
258061da546Spatrick   // packets in response to a ^C packet. Additionally, all debugservers still
259061da546Spatrick   // return two stop replies if the inferior stops due to some other reason
260061da546Spatrick   // before the remote stub manages to interrupt it. We need to wait for this
261061da546Spatrick   // additional packet to make sure the packet sequence does not get skewed.
262061da546Spatrick   StringExtractorGDBRemote extra_stop_reply_packet;
263061da546Spatrick   ReadPacket(extra_stop_reply_packet, milliseconds(100), false);
264061da546Spatrick 
265061da546Spatrick   // Interrupting is typically done using SIGSTOP or SIGINT, so if the process
266061da546Spatrick   // stops with some other signal, we definitely want to stop.
267061da546Spatrick   const uint8_t signo = response.GetHexU8(UINT8_MAX);
268061da546Spatrick   if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
269061da546Spatrick       signo != signals.GetSignalNumberFromName("SIGINT"))
270061da546Spatrick     return true;
271061da546Spatrick 
272061da546Spatrick   // We probably only stopped to perform some async processing, so continue
273061da546Spatrick   // after that is done.
274061da546Spatrick   // TODO: This is not 100% correct, as the process may have been stopped with
275061da546Spatrick   // SIGINT or SIGSTOP that was not caused by us (e.g. raise(SIGINT)). This will
276061da546Spatrick   // normally cause a stop, but if it's done concurrently with a async
277061da546Spatrick   // interrupt, that stop will get eaten (llvm.org/pr20231).
278061da546Spatrick   return false;
279061da546Spatrick }
280061da546Spatrick 
281061da546Spatrick void GDBRemoteClientBase::OnRunPacketSent(bool first) {
282061da546Spatrick   if (first)
283061da546Spatrick     BroadcastEvent(eBroadcastBitRunPacketSent, nullptr);
284061da546Spatrick }
285061da546Spatrick 
286061da546Spatrick ///////////////////////////////////////
287061da546Spatrick // GDBRemoteClientBase::ContinueLock //
288061da546Spatrick ///////////////////////////////////////
289061da546Spatrick 
290061da546Spatrick GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm)
291061da546Spatrick     : m_comm(comm), m_acquired(false) {
292061da546Spatrick   lock();
293061da546Spatrick }
294061da546Spatrick 
295061da546Spatrick GDBRemoteClientBase::ContinueLock::~ContinueLock() {
296061da546Spatrick   if (m_acquired)
297061da546Spatrick     unlock();
298061da546Spatrick }
299061da546Spatrick 
300061da546Spatrick void GDBRemoteClientBase::ContinueLock::unlock() {
301061da546Spatrick   lldbassert(m_acquired);
302061da546Spatrick   {
303061da546Spatrick     std::unique_lock<std::mutex> lock(m_comm.m_mutex);
304061da546Spatrick     m_comm.m_is_running = false;
305061da546Spatrick   }
306061da546Spatrick   m_comm.m_cv.notify_all();
307061da546Spatrick   m_acquired = false;
308061da546Spatrick }
309061da546Spatrick 
310061da546Spatrick GDBRemoteClientBase::ContinueLock::LockResult
311061da546Spatrick GDBRemoteClientBase::ContinueLock::lock() {
312061da546Spatrick   Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
313061da546Spatrick   LLDB_LOGF(log, "GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
314061da546Spatrick             __FUNCTION__, m_comm.m_continue_packet.c_str());
315061da546Spatrick 
316061da546Spatrick   lldbassert(!m_acquired);
317061da546Spatrick   std::unique_lock<std::mutex> lock(m_comm.m_mutex);
318061da546Spatrick   m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; });
319061da546Spatrick   if (m_comm.m_should_stop) {
320061da546Spatrick     m_comm.m_should_stop = false;
321061da546Spatrick     LLDB_LOGF(log, "GDBRemoteClientBase::ContinueLock::%s() cancelled",
322061da546Spatrick               __FUNCTION__);
323061da546Spatrick     return LockResult::Cancelled;
324061da546Spatrick   }
325061da546Spatrick   if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) !=
326061da546Spatrick       PacketResult::Success)
327061da546Spatrick     return LockResult::Failed;
328061da546Spatrick 
329061da546Spatrick   lldbassert(!m_comm.m_is_running);
330061da546Spatrick   m_comm.m_is_running = true;
331061da546Spatrick   m_acquired = true;
332061da546Spatrick   return LockResult::Success;
333061da546Spatrick }
334061da546Spatrick 
335061da546Spatrick ///////////////////////////////
336061da546Spatrick // GDBRemoteClientBase::Lock //
337061da546Spatrick ///////////////////////////////
338061da546Spatrick 
339061da546Spatrick GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
340061da546Spatrick     : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
341061da546Spatrick       m_acquired(false), m_did_interrupt(false) {
342061da546Spatrick   SyncWithContinueThread(interrupt);
343061da546Spatrick   if (m_acquired)
344061da546Spatrick     m_async_lock.lock();
345061da546Spatrick }
346061da546Spatrick 
347061da546Spatrick void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
348061da546Spatrick   Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
349061da546Spatrick   std::unique_lock<std::mutex> lock(m_comm.m_mutex);
350061da546Spatrick   if (m_comm.m_is_running && !interrupt)
351061da546Spatrick     return; // We were asked to avoid interrupting the sender. Lock is not
352061da546Spatrick             // acquired.
353061da546Spatrick 
354061da546Spatrick   ++m_comm.m_async_count;
355061da546Spatrick   if (m_comm.m_is_running) {
356061da546Spatrick     if (m_comm.m_async_count == 1) {
357061da546Spatrick       // The sender has sent the continue packet and we are the first async
358061da546Spatrick       // packet. Let's interrupt it.
359061da546Spatrick       const char ctrl_c = '\x03';
360061da546Spatrick       ConnectionStatus status = eConnectionStatusSuccess;
361061da546Spatrick       size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, nullptr);
362061da546Spatrick       if (bytes_written == 0) {
363061da546Spatrick         --m_comm.m_async_count;
364061da546Spatrick         LLDB_LOGF(log, "GDBRemoteClientBase::Lock::Lock failed to send "
365061da546Spatrick                        "interrupt packet");
366061da546Spatrick         return;
367061da546Spatrick       }
368061da546Spatrick       if (log)
369061da546Spatrick         log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
370061da546Spatrick       m_comm.m_interrupt_time = steady_clock::now();
371061da546Spatrick     }
372061da546Spatrick     m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });
373061da546Spatrick     m_did_interrupt = true;
374061da546Spatrick   }
375061da546Spatrick   m_acquired = true;
376061da546Spatrick }
377061da546Spatrick 
378061da546Spatrick GDBRemoteClientBase::Lock::~Lock() {
379061da546Spatrick   if (!m_acquired)
380061da546Spatrick     return;
381061da546Spatrick   {
382061da546Spatrick     std::unique_lock<std::mutex> lock(m_comm.m_mutex);
383061da546Spatrick     --m_comm.m_async_count;
384061da546Spatrick   }
385061da546Spatrick   m_comm.m_cv.notify_one();
386061da546Spatrick }
387