LLDB  mainline
StringExtractorGDBRemote.cpp
Go to the documentation of this file.
1 //===-- StringExtractorGDBRemote.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 
10 
11 #include <ctype.h>
12 #include <string.h>
13 
16  if (m_packet.empty())
17  return eUnsupported;
18 
19  switch (m_packet[0]) {
20  case 'E':
21  if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) {
22  if (m_packet.size() == 3)
23  return eError;
24  llvm::StringRef packet_ref(m_packet);
25  if (packet_ref[3] == ';') {
26  auto err_string = packet_ref.substr(4);
27  for (auto e : err_string)
28  if (!isxdigit(e))
29  return eResponse;
30  return eError;
31  }
32  }
33  break;
34 
35  case 'O':
36  if (m_packet.size() == 2 && m_packet[1] == 'K')
37  return eOK;
38  break;
39 
40  case '+':
41  if (m_packet.size() == 1)
42  return eAck;
43  break;
44 
45  case '-':
46  if (m_packet.size() == 1)
47  return eNack;
48  break;
49  }
50  return eResponse;
51 }
52 
55 #define PACKET_MATCHES(s) \
56  ((packet_size == (sizeof(s) - 1)) && (strcmp((packet_cstr), (s)) == 0))
57 #define PACKET_STARTS_WITH(s) \
58  ((packet_size >= (sizeof(s) - 1)) && \
59  ::strncmp(packet_cstr, s, (sizeof(s) - 1)) == 0)
60 
61  // Empty is not a supported packet...
62  if (m_packet.empty())
64 
65  const size_t packet_size = m_packet.size();
66  const char *packet_cstr = m_packet.c_str();
67  switch (m_packet[0]) {
68 
69  case '%':
71 
72  case '\x03':
73  if (packet_size == 1)
75  break;
76 
77  case '-':
78  if (packet_size == 1)
80  break;
81 
82  case '+':
83  if (packet_size == 1)
84  return eServerPacketType_ack;
85  break;
86 
87  case 'A':
88  return eServerPacketType_A;
89 
90  case 'Q':
91 
92  switch (packet_cstr[1]) {
93  case 'E':
94  if (PACKET_STARTS_WITH("QEnvironment:"))
96  if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
98  if (PACKET_STARTS_WITH("QEnableErrorStrings"))
100  break;
101 
102  case 'P':
103  if (PACKET_STARTS_WITH("QPassSignals:"))
105  break;
106 
107  case 'S':
108  if (PACKET_MATCHES("QStartNoAckMode"))
110  if (PACKET_STARTS_WITH("QSaveRegisterState"))
112  if (PACKET_STARTS_WITH("QSetDisableASLR:"))
114  if (PACKET_STARTS_WITH("QSetDetachOnError:"))
116  if (PACKET_STARTS_WITH("QSetSTDIN:"))
118  if (PACKET_STARTS_WITH("QSetSTDOUT:"))
120  if (PACKET_STARTS_WITH("QSetSTDERR:"))
122  if (PACKET_STARTS_WITH("QSetWorkingDir:"))
124  if (PACKET_STARTS_WITH("QSetLogging:"))
126  if (PACKET_STARTS_WITH("QSetMaxPacketSize:"))
128  if (PACKET_STARTS_WITH("QSetMaxPayloadSize:"))
130  if (PACKET_STARTS_WITH("QSetEnableAsyncProfiling;"))
132  if (PACKET_STARTS_WITH("QSyncThreadState:"))
134  break;
135 
136  case 'L':
137  if (PACKET_STARTS_WITH("QLaunchArch:"))
139  if (PACKET_MATCHES("QListThreadsInStopReply"))
141  break;
142 
143  case 'R':
144  if (PACKET_STARTS_WITH("QRestoreRegisterState:"))
146  break;
147 
148  case 'T':
149  if (PACKET_MATCHES("QThreadSuffixSupported"))
151  break;
152  }
153  break;
154 
155  case 'q':
156  switch (packet_cstr[1]) {
157  case 's':
158  if (PACKET_MATCHES("qsProcessInfo"))
160  if (PACKET_MATCHES("qsThreadInfo"))
162  break;
163 
164  case 'f':
165  if (PACKET_STARTS_WITH("qfProcessInfo"))
167  if (PACKET_STARTS_WITH("qfThreadInfo"))
169  break;
170 
171  case 'C':
172  if (packet_size == 2)
173  return eServerPacketType_qC;
174  break;
175 
176  case 'E':
177  if (PACKET_STARTS_WITH("qEcho:"))
179  break;
180 
181  case 'F':
182  if (PACKET_STARTS_WITH("qFileLoadAddress:"))
184  break;
185 
186  case 'G':
187  if (PACKET_STARTS_WITH("qGroupName:"))
189  if (PACKET_MATCHES("qGetWorkingDir"))
191  if (PACKET_MATCHES("qGetPid"))
193  if (PACKET_STARTS_WITH("qGetProfileData;"))
195  if (PACKET_MATCHES("qGDBServerVersion"))
197  break;
198 
199  case 'H':
200  if (PACKET_MATCHES("qHostInfo"))
202  break;
203 
204  case 'K':
205  if (PACKET_STARTS_WITH("qKillSpawnedProcess"))
207  break;
208 
209  case 'L':
210  if (PACKET_STARTS_WITH("qLaunchGDBServer"))
212  if (PACKET_MATCHES("qLaunchSuccess"))
214  break;
215 
216  case 'M':
217  if (PACKET_STARTS_WITH("qMemoryRegionInfo:"))
219  if (PACKET_MATCHES("qMemoryRegionInfo"))
221  if (PACKET_STARTS_WITH("qModuleInfo:"))
223  break;
224 
225  case 'P':
226  if (PACKET_STARTS_WITH("qProcessInfoPID:"))
228  if (PACKET_STARTS_WITH("qPlatform_shell:"))
230  if (PACKET_STARTS_WITH("qPlatform_mkdir:"))
232  if (PACKET_STARTS_WITH("qPlatform_chmod:"))
234  if (PACKET_MATCHES("qProcessInfo"))
236  break;
237 
238  case 'Q':
239  if (PACKET_MATCHES("qQueryGDBServer"))
241  break;
242 
243  case 'R':
244  if (PACKET_STARTS_WITH("qRcmd,"))
246  if (PACKET_STARTS_WITH("qRegisterInfo"))
248  break;
249 
250  case 'S':
251  if (PACKET_STARTS_WITH("qSpeedTest:"))
253  if (PACKET_MATCHES("qShlibInfoAddr"))
255  if (PACKET_MATCHES("qStepPacketSupported"))
257  if (PACKET_STARTS_WITH("qSupported"))
259  if (PACKET_MATCHES("qSyncThreadStateSupported"))
261  break;
262 
263  case 'T':
264  if (PACKET_STARTS_WITH("qThreadExtraInfo,"))
266  if (PACKET_STARTS_WITH("qThreadStopInfo"))
268  break;
269 
270  case 'U':
271  if (PACKET_STARTS_WITH("qUserName:"))
273  break;
274 
275  case 'V':
276  if (PACKET_MATCHES("qVAttachOrWaitSupported"))
278  break;
279 
280  case 'W':
281  if (PACKET_STARTS_WITH("qWatchpointSupportInfo:"))
283  if (PACKET_MATCHES("qWatchpointSupportInfo"))
285  break;
286 
287  case 'X':
288  if (PACKET_STARTS_WITH("qXfer:auxv:read::"))
290  break;
291  }
292  break;
293 
294  case 'j':
295  if (PACKET_STARTS_WITH("jModulesInfo:"))
297  if (PACKET_MATCHES("jSignalsInfo"))
299  if (PACKET_MATCHES("jThreadsInfo"))
301  if (PACKET_STARTS_WITH("jTraceBufferRead:"))
303  if (PACKET_STARTS_WITH("jTraceConfigRead:"))
305  if (PACKET_STARTS_WITH("jTraceMetaRead:"))
307  if (PACKET_STARTS_WITH("jTraceStart:"))
309  if (PACKET_STARTS_WITH("jTraceStop:"))
311  break;
312 
313  case 'v':
314  if (PACKET_STARTS_WITH("vFile:")) {
315  if (PACKET_STARTS_WITH("vFile:open:"))
317  else if (PACKET_STARTS_WITH("vFile:close:"))
319  else if (PACKET_STARTS_WITH("vFile:pread"))
321  else if (PACKET_STARTS_WITH("vFile:pwrite"))
323  else if (PACKET_STARTS_WITH("vFile:size"))
325  else if (PACKET_STARTS_WITH("vFile:exists"))
327  else if (PACKET_STARTS_WITH("vFile:stat"))
329  else if (PACKET_STARTS_WITH("vFile:mode"))
331  else if (PACKET_STARTS_WITH("vFile:MD5"))
333  else if (PACKET_STARTS_WITH("vFile:symlink"))
335  else if (PACKET_STARTS_WITH("vFile:unlink"))
337 
338  } else {
339  if (PACKET_STARTS_WITH("vAttach;"))
341  if (PACKET_STARTS_WITH("vAttachWait;"))
343  if (PACKET_STARTS_WITH("vAttachOrWait;"))
345  if (PACKET_STARTS_WITH("vAttachName;"))
347  if (PACKET_STARTS_WITH("vCont;"))
349  if (PACKET_MATCHES("vCont?"))
351  }
352  break;
353  case '_':
354  switch (packet_cstr[1]) {
355  case 'M':
356  return eServerPacketType__M;
357 
358  case 'm':
359  return eServerPacketType__m;
360  }
361  break;
362 
363  case '?':
364  if (packet_size == 1)
366  break;
367 
368  case 'c':
369  return eServerPacketType_c;
370 
371  case 'C':
372  return eServerPacketType_C;
373 
374  case 'D':
375  if (packet_size == 1)
376  return eServerPacketType_D;
377  break;
378 
379  case 'g':
380  if (packet_size == 1)
381  return eServerPacketType_g;
382  break;
383 
384  case 'G':
385  return eServerPacketType_G;
386 
387  case 'H':
388  return eServerPacketType_H;
389 
390  case 'I':
391  return eServerPacketType_I;
392 
393  case 'k':
394  if (packet_size == 1)
395  return eServerPacketType_k;
396  break;
397 
398  case 'm':
399  return eServerPacketType_m;
400 
401  case 'M':
402  return eServerPacketType_M;
403 
404  case 'p':
405  return eServerPacketType_p;
406 
407  case 'P':
408  return eServerPacketType_P;
409 
410  case 's':
411  if (packet_size == 1)
412  return eServerPacketType_s;
413  break;
414 
415  case 'S':
416  return eServerPacketType_S;
417 
418  case 'x':
419  return eServerPacketType_x;
420 
421  case 'X':
422  return eServerPacketType_X;
423 
424  case 'T':
425  return eServerPacketType_T;
426 
427  case 'z':
428  if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
429  return eServerPacketType_z;
430  break;
431 
432  case 'Z':
433  if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
434  return eServerPacketType_Z;
435  break;
436  }
438 }
439 
441  return GetResponseType() == eOK;
442 }
443 
445  return GetResponseType() == eUnsupported;
446 }
447 
449  return GetResponseType() == eResponse;
450 }
451 
453  return GetResponseType() == eError && isxdigit(m_packet[1]) &&
454  isxdigit(m_packet[2]);
455 }
456 
458  if (GetResponseType() == eError) {
459  SetFilePos(1);
460  return GetHexU8(255);
461  }
462  return 0;
463 }
464 
466  lldb_private::Status error;
467  if (GetResponseType() == eError) {
468  SetFilePos(1);
469  uint8_t errc = GetHexU8(255);
470  error.SetError(errc, lldb::eErrorTypeGeneric);
471 
472  error.SetErrorStringWithFormat("Error %u", errc);
473  std::string error_messg;
474  if (GetChar() == ';') {
475  GetHexByteString(error_messg);
476  error.SetErrorString(error_messg);
477  }
478  }
479  return error;
480 }
481 
483  // Just get the data bytes in the string as
484  // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
485  // characters. If any 0x7d characters are left in the packet, then they are
486  // supposed to be there...
487  str.clear();
488  const size_t bytes_left = GetBytesLeft();
489  if (bytes_left > 0) {
490  str.assign(m_packet, m_index, bytes_left);
491  m_index += bytes_left;
492  }
493  return str.size();
494 }
495 
496 static bool
498  const StringExtractorGDBRemote &response) {
499  switch (response.GetResponseType()) {
503  return true;
504 
508  break;
509  }
510  return false;
511 }
512 
513 static bool JSONResponseValidator(void *,
514  const StringExtractorGDBRemote &response) {
515  switch (response.GetResponseType()) {
518  return true; // Accept unsupported or EXX as valid responses
519 
523  break;
524 
526  // JSON that is returned in from JSON query packets is currently always
527  // either a dictionary which starts with a '{', or an array which starts
528  // with a '['. This is a quick validator to just make sure the response
529  // could be valid JSON without having to validate all of the
530  // JSON content.
531  switch (response.GetStringRef()[0]) {
532  case '{':
533  return true;
534  case '[':
535  return true;
536  default:
537  break;
538  }
539  break;
540  }
541  return false;
542 }
543 
544 static bool
546  const StringExtractorGDBRemote &response) {
547  switch (response.GetResponseType()) {
550  return true; // Accept unsupported or EXX as valid responses
551 
555  break;
556 
558  uint32_t valid_count = 0;
559  for (const char ch : response.GetStringRef()) {
560  if (!isxdigit(ch)) {
561  return false;
562  }
563  if (++valid_count >= 16)
564  break; // Don't validate all the characters in case the packet is very
565  // large
566  }
567  return true;
568  } break;
569  }
570  return false;
571 }
572 
574  const StringExtractorGDBRemote &rhs) {
575  m_validator = rhs.m_validator;
577 }
578 
580  ResponseValidatorCallback callback, void *baton) {
581  m_validator = callback;
582  m_validator_baton = baton;
583 }
584 
587  m_validator_baton = nullptr;
588 }
589 
592  m_validator_baton = nullptr;
593 }
594 
597  m_validator_baton = nullptr;
598 }
599 
601  // If we have a validator callback, try to validate the callback
602  if (m_validator)
603  return m_validator(m_validator_baton, *this);
604  else
605  return true; // No validator, so response is valid
606 }
uint8_t GetHexU8(uint8_t fail_value=0, bool set_eof_on_fail=true)
#define PACKET_STARTS_WITH(s)
std::string m_packet
void SetResponseValidator(ResponseValidatorCallback callback, void *baton)
size_t GetHexByteString(std::string &str)
ResponseValidatorCallback m_validator
ServerPacketType GetServerPacketType() const
void SetFilePos(uint32_t idx)
#define PACKET_MATCHES(s)
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
void CopyResponseValidator(const StringExtractorGDBRemote &rhs)
size_t GetBytesLeft()
Generic errors that can be any value.
size_t GetEscapedBinaryData(std::string &str)
static bool JSONResponseValidator(void *, const StringExtractorGDBRemote &response)
int void SetError(ValueType err, lldb::ErrorType type)
Set accesssor with an error value and type.
Definition: Status.cpp:216
static bool ASCIIHexBytesResponseValidator(void *, const StringExtractorGDBRemote &response)
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
std::string & GetStringRef()
ResponseType GetResponseType() const
bool(* ResponseValidatorCallback)(void *baton, const StringExtractorGDBRemote &response)
char GetChar(char fail_value='\0')
static bool OKErrorNotSupportedResponseValidator(void *, const StringExtractorGDBRemote &response)
An error handling class.
Definition: Status.h:44