LLDB  mainline
GDBRemoteClientBase.cpp
Go to the documentation of this file.
1 //===-- GDBRemoteClientBase.cpp ---------------------------------*- C++ -*-===//
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 
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 static const seconds kInterruptTimeout(5);
24 
25 /////////////////////////
26 // GDBRemoteClientBase //
27 /////////////////////////
28 
29 GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default;
30 
31 GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name,
32  const char *listener_name)
33  : GDBRemoteCommunication(comm_name, listener_name), m_async_count(0),
34  m_is_running(false), m_should_stop(false) {}
35 
37  ContinueDelegate &delegate, const UnixSignals &signals,
38  llvm::StringRef payload, StringExtractorGDBRemote &response) {
40  response.Clear();
41 
42  {
43  std::lock_guard<std::mutex> lock(m_mutex);
44  m_continue_packet = payload;
45  m_should_stop = false;
46  }
47  ContinueLock cont_lock(*this);
48  if (!cont_lock)
49  return eStateInvalid;
50  OnRunPacketSent(true);
51 
52  for (;;) {
53  PacketResult read_result = ReadPacket(response, kInterruptTimeout, false);
54  switch (read_result) {
56  std::lock_guard<std::mutex> lock(m_mutex);
57  if (m_async_count == 0)
58  continue;
59  if (steady_clock::now() >= m_interrupt_time + kInterruptTimeout)
60  return eStateInvalid;
61  break;
62  }
64  break;
65  default:
66  if (log)
67  log->Printf("GDBRemoteClientBase::%s () ReadPacket(...) => false",
68  __FUNCTION__);
69  return eStateInvalid;
70  }
71  if (response.Empty())
72  return eStateInvalid;
73 
74  const char stop_type = response.GetChar();
75  if (log)
76  log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
77  response.GetStringRef().c_str());
78 
79  switch (stop_type) {
80  case 'W':
81  case 'X':
82  return eStateExited;
83  case 'E':
84  // ERROR
85  return eStateInvalid;
86  default:
87  if (log)
88  log->Printf("GDBRemoteClientBase::%s () unrecognized async packet",
89  __FUNCTION__);
90  return eStateInvalid;
91  case 'O': {
92  std::string inferior_stdout;
93  response.GetHexByteString(inferior_stdout);
94  delegate.HandleAsyncStdout(inferior_stdout);
95  break;
96  }
97  case 'A':
98  delegate.HandleAsyncMisc(
99  llvm::StringRef(response.GetStringRef()).substr(1));
100  break;
101  case 'J':
102  delegate.HandleAsyncStructuredDataPacket(response.GetStringRef());
103  break;
104  case 'T':
105  case 'S':
106  // Do this with the continue lock held.
107  const bool should_stop = ShouldStop(signals, response);
108  response.SetFilePos(0);
109 
110  // The packet we should resume with. In the future we should check our
111  // thread list and "do the right thing" for new threads that show up
112  // while we stop and run async packets. Setting the packet to 'c' to
113  // continue all threads is the right thing to do 99.99% of the time
114  // because if a thread was single stepping, and we sent an interrupt, we
115  // will notice above that we didn't stop due to an interrupt but stopped
116  // due to stepping and we would _not_ continue. This packet may get
117  // modified by the async actions (e.g. to send a signal).
118  m_continue_packet = 'c';
119  cont_lock.unlock();
120 
121  delegate.HandleStopReply();
122  if (should_stop)
123  return eStateStopped;
124 
125  switch (cont_lock.lock()) {
126  case ContinueLock::LockResult::Success:
127  break;
128  case ContinueLock::LockResult::Failed:
129  return eStateInvalid;
130  case ContinueLock::LockResult::Cancelled:
131  return eStateStopped;
132  }
133  OnRunPacketSent(false);
134  break;
135  }
136  }
137 }
138 
140  Lock lock(*this, true);
141  if (!lock || !lock.DidInterrupt())
142  return false;
143 
144  m_continue_packet = 'C';
145  m_continue_packet += llvm::hexdigit((signo / 16) % 16);
146  m_continue_packet += llvm::hexdigit(signo % 16);
147  return true;
148 }
149 
151  Lock lock(*this, true);
152  if (!lock.DidInterrupt())
153  return false;
154  m_should_stop = true;
155  return true;
156 }
159  llvm::StringRef payload, StringExtractorGDBRemote &response,
160  bool send_async) {
161  Lock lock(*this, send_async);
162  if (!lock) {
163  if (Log *log =
165  log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending "
166  "packet '%.*s' (send_async=%d)",
167  __FUNCTION__, int(payload.size()), payload.data(),
168  send_async);
170  }
171 
172  return SendPacketAndWaitForResponseNoLock(payload, response);
173 }
174 
177  llvm::StringRef payload, StringExtractorGDBRemote &response,
178  bool send_async,
179  llvm::function_ref<void(llvm::StringRef)> output_callback) {
180  Lock lock(*this, send_async);
181  if (!lock) {
182  if (Log *log =
184  log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending "
185  "packet '%.*s' (send_async=%d)",
186  __FUNCTION__, int(payload.size()), payload.data(),
187  send_async);
189  }
190 
191  PacketResult packet_result = SendPacketNoLock(payload);
192  if (packet_result != PacketResult::Success)
193  return packet_result;
194 
195  return ReadPacketWithOutputSupport(response, GetPacketTimeout(), true,
196  output_callback);
197 }
198 
201  llvm::StringRef payload, StringExtractorGDBRemote &response) {
202  PacketResult packet_result = SendPacketNoLock(payload);
203  if (packet_result != PacketResult::Success)
204  return packet_result;
205 
206  const size_t max_response_retries = 3;
207  for (size_t i = 0; i < max_response_retries; ++i) {
208  packet_result = ReadPacket(response, GetPacketTimeout(), true);
209  // Make sure we received a response
210  if (packet_result != PacketResult::Success)
211  return packet_result;
212  // Make sure our response is valid for the payload that was sent
213  if (response.ValidateResponse())
214  return packet_result;
215  // Response says it wasn't valid
217  if (log)
218  log->Printf(
219  "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
220  int(payload.size()), payload.data(), response.GetStringRef().c_str(),
221  (i == (max_response_retries - 1))
222  ? "using invalid response and giving up"
223  : "ignoring response and waiting for another");
224  }
225  return packet_result;
226 }
227 
228 bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload,
229  StringExtractorGDBRemote &response) {
231  if (log)
232  log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
233 
234  // we want to lock down packet sending while we continue
235  Lock lock(*this, true);
236 
237  if (log)
238  log->Printf(
239  "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s",
240  __FUNCTION__, int(payload.size()), payload.data());
241 
242  if (SendPacketNoLock(payload) != PacketResult::Success)
243  return false;
244 
245  OnRunPacketSent(true);
246 
247  // wait for the response to the vCont
248  if (ReadPacket(response, llvm::None, false) == PacketResult::Success) {
249  if (response.IsOKResponse())
250  return true;
251  }
252 
253  return false;
254 }
255 bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
256  StringExtractorGDBRemote &response) {
257  std::lock_guard<std::mutex> lock(m_mutex);
258 
259  if (m_async_count == 0)
260  return true; // We were not interrupted. The process stopped on its own.
261 
262  // Older debugserver stubs (before April 2016) can return two stop-reply
263  // packets in response to a ^C packet. Additionally, all debugservers still
264  // return two stop replies if the inferior stops due to some other reason
265  // before the remote stub manages to interrupt it. We need to wait for this
266  // additional packet to make sure the packet sequence does not get skewed.
267  StringExtractorGDBRemote extra_stop_reply_packet;
268  ReadPacket(extra_stop_reply_packet, milliseconds(100), false);
269 
270  // Interrupting is typically done using SIGSTOP or SIGINT, so if the process
271  // stops with some other signal, we definitely want to stop.
272  const uint8_t signo = response.GetHexU8(UINT8_MAX);
273  if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
274  signo != signals.GetSignalNumberFromName("SIGINT"))
275  return true;
276 
277  // We probably only stopped to perform some async processing, so continue
278  // after that is done.
279  // TODO: This is not 100% correct, as the process may have been stopped with
280  // SIGINT or SIGSTOP that was not caused by us (e.g. raise(SIGINT)). This will
281  // normally cause a stop, but if it's done concurrently with a async
282  // interrupt, that stop will get eaten (llvm.org/pr20231).
283  return false;
284 }
285 
287  if (first)
289 }
290 
291 ///////////////////////////////////////
292 // GDBRemoteClientBase::ContinueLock //
293 ///////////////////////////////////////
294 
295 GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm)
296  : m_comm(comm), m_acquired(false) {
297  lock();
298 }
299 
300 GDBRemoteClientBase::ContinueLock::~ContinueLock() {
301  if (m_acquired)
302  unlock();
303 }
304 
305 void GDBRemoteClientBase::ContinueLock::unlock() {
306  lldbassert(m_acquired);
307  {
308  std::unique_lock<std::mutex> lock(m_comm.m_mutex);
309  m_comm.m_is_running = false;
310  }
311  m_comm.m_cv.notify_all();
312  m_acquired = false;
313 }
314 
315 GDBRemoteClientBase::ContinueLock::LockResult
316 GDBRemoteClientBase::ContinueLock::lock() {
318  if (log)
319  log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
320  __FUNCTION__, m_comm.m_continue_packet.c_str());
321 
322  lldbassert(!m_acquired);
323  std::unique_lock<std::mutex> lock(m_comm.m_mutex);
324  m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; });
325  if (m_comm.m_should_stop) {
326  m_comm.m_should_stop = false;
327  if (log)
328  log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled",
329  __FUNCTION__);
330  return LockResult::Cancelled;
331  }
332  if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) !=
334  return LockResult::Failed;
335 
336  lldbassert(!m_comm.m_is_running);
337  m_comm.m_is_running = true;
338  m_acquired = true;
339  return LockResult::Success;
340 }
341 
342 ///////////////////////////////
343 // GDBRemoteClientBase::Lock //
344 ///////////////////////////////
345 
347  : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
348  m_acquired(false), m_did_interrupt(false) {
349  SyncWithContinueThread(interrupt);
350  if (m_acquired)
351  m_async_lock.lock();
352 }
353 
354 void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
356  std::unique_lock<std::mutex> lock(m_comm.m_mutex);
357  if (m_comm.m_is_running && !interrupt)
358  return; // We were asked to avoid interrupting the sender. Lock is not
359  // acquired.
360 
361  ++m_comm.m_async_count;
362  if (m_comm.m_is_running) {
363  if (m_comm.m_async_count == 1) {
364  // The sender has sent the continue packet and we are the first async
365  // packet. Let's interrupt it.
366  const char ctrl_c = '\x03';
368  size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL);
369  if (bytes_written == 0) {
370  --m_comm.m_async_count;
371  if (log)
372  log->Printf("GDBRemoteClientBase::Lock::Lock failed to send "
373  "interrupt packet");
374  return;
375  }
376  if (log)
377  log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
378  m_comm.m_interrupt_time = steady_clock::now();
379  }
380  m_comm.m_cv.wait(lock, [this] { return !m_comm.m_is_running; });
381  m_did_interrupt = true;
382  }
383  m_acquired = true;
384 }
385 
387  if (!m_acquired)
388  return;
389  {
390  std::unique_lock<std::mutex> lock(m_comm.m_mutex);
391  --m_comm.m_async_count;
392  }
393  m_comm.m_cv.notify_one();
394 }
PacketResult SendPacketAndWaitForResponseNoLock(llvm::StringRef payload, StringExtractorGDBRemote &response)
uint8_t GetHexU8(uint8_t fail_value=0, bool set_eof_on_fail=true)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
#define lldbassert(x)
Definition: LLDBAssert.h:15
bool SendvContPacket(llvm::StringRef payload, StringExtractorGDBRemote &response)
PacketResult SendPacketAndReceiveResponseWithOutputSupport(llvm::StringRef payload, StringExtractorGDBRemote &response, bool send_async, llvm::function_ref< void(llvm::StringRef)> output_callback)
size_t GetHexByteString(std::string &str)
Process or thread is stopped and can be examined.
PacketResult ReadPacketWithOutputSupport(StringExtractorGDBRemote &response, Timeout< std::micro > timeout, bool sync_on_timeout, llvm::function_ref< void(llvm::StringRef)> output_callback)
virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data)=0
Process asynchronously-received structured data.
void BroadcastEvent(lldb::EventSP &event_sp)
Broadcast an event which has no associated data.
Definition: Broadcaster.h:283
Process has exited and can&#39;t be examined.
static const seconds kInterruptTimeout(5)
#define GDBR_LOG_PROCESS
void SetFilePos(uint32_t idx)
lldb::StateType SendContinuePacketAndWaitForResponse(ContinueDelegate &delegate, const UnixSignals &signals, llvm::StringRef payload, StringExtractorGDBRemote &response)
PacketResult ReadPacket(StringExtractorGDBRemote &response, Timeout< std::micro > timeout, bool sync_on_timeout)
int32_t GetSignalNumberFromName(const char *name) const
void PutCString(const char *cstr)
Definition: Log.cpp:109
Definition: SBAddress.h:15
std::string & GetStringRef()
PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload, StringExtractorGDBRemote &response, bool send_async)
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
char GetChar(char fail_value='\0')
#define GDBR_LOG_PACKETS
size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, Status *error_ptr)
The actual write function that attempts to write to the communications protocol.