LLDB  mainline
StringExtractorGDBRemote.cpp
Go to the documentation of this file.
1 //===-- StringExtractorGDBRemote.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 
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:"))
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  return eServerPacketType_g;
381 
382  case 'G':
383  return eServerPacketType_G;
384 
385  case 'H':
386  return eServerPacketType_H;
387 
388  case 'I':
389  return eServerPacketType_I;
390 
391  case 'k':
392  if (packet_size == 1)
393  return eServerPacketType_k;
394  break;
395 
396  case 'm':
397  return eServerPacketType_m;
398 
399  case 'M':
400  return eServerPacketType_M;
401 
402  case 'p':
403  return eServerPacketType_p;
404 
405  case 'P':
406  return eServerPacketType_P;
407 
408  case 's':
409  if (packet_size == 1)
410  return eServerPacketType_s;
411  break;
412 
413  case 'S':
414  return eServerPacketType_S;
415 
416  case 'x':
417  return eServerPacketType_x;
418 
419  case 'X':
420  return eServerPacketType_X;
421 
422  case 'T':
423  return eServerPacketType_T;
424 
425  case 'z':
426  if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
427  return eServerPacketType_z;
428  break;
429 
430  case 'Z':
431  if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
432  return eServerPacketType_Z;
433  break;
434  }
436 }
437 
439  return GetResponseType() == eOK;
440 }
441 
443  return GetResponseType() == eUnsupported;
444 }
445 
447  return GetResponseType() == eResponse;
448 }
449 
451  return GetResponseType() == eError && isxdigit(m_packet[1]) &&
452  isxdigit(m_packet[2]);
453 }
454 
456  if (GetResponseType() == eError) {
457  SetFilePos(1);
458  return GetHexU8(255);
459  }
460  return 0;
461 }
462 
465  if (GetResponseType() == eError) {
466  SetFilePos(1);
467  uint8_t errc = GetHexU8(255);
468  error.SetError(errc, lldb::eErrorTypeGeneric);
469 
470  error.SetErrorStringWithFormat("Error %u", errc);
471  std::string error_messg;
472  if (GetChar() == ';') {
473  GetHexByteString(error_messg);
474  error.SetErrorString(error_messg);
475  }
476  }
477  return error;
478 }
479 
481  // Just get the data bytes in the string as
482  // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
483  // characters. If any 0x7d characters are left in the packet, then they are
484  // supposed to be there...
485  str.clear();
486  const size_t bytes_left = GetBytesLeft();
487  if (bytes_left > 0) {
488  str.assign(m_packet, m_index, bytes_left);
489  m_index += bytes_left;
490  }
491  return str.size();
492 }
493 
494 static bool
496  const StringExtractorGDBRemote &response) {
497  switch (response.GetResponseType()) {
501  return true;
502 
506  break;
507  }
508  return false;
509 }
510 
511 static bool JSONResponseValidator(void *,
512  const StringExtractorGDBRemote &response) {
513  switch (response.GetResponseType()) {
516  return true; // Accept unsupported or EXX as valid responses
517 
521  break;
522 
524  // JSON that is returned in from JSON query packets is currently always
525  // either a dictionary which starts with a '{', or an array which starts
526  // with a '['. This is a quick validator to just make sure the response
527  // could be valid JSON without having to validate all of the
528  // JSON content.
529  switch (response.GetStringRef()[0]) {
530  case '{':
531  return true;
532  case '[':
533  return true;
534  default:
535  break;
536  }
537  break;
538  }
539  return false;
540 }
541 
542 static bool
544  const StringExtractorGDBRemote &response) {
545  switch (response.GetResponseType()) {
548  return true; // Accept unsupported or EXX as valid responses
549 
553  break;
554 
556  uint32_t valid_count = 0;
557  for (const char ch : response.GetStringRef()) {
558  if (!isxdigit(ch)) {
559  return false;
560  }
561  if (++valid_count >= 16)
562  break; // Don't validate all the characters in case the packet is very
563  // large
564  }
565  return true;
566  } break;
567  }
568  return false;
569 }
570 
572  const StringExtractorGDBRemote &rhs) {
573  m_validator = rhs.m_validator;
575 }
576 
578  ResponseValidatorCallback callback, void *baton) {
579  m_validator = callback;
580  m_validator_baton = baton;
581 }
582 
585  m_validator_baton = nullptr;
586 }
587 
590  m_validator_baton = nullptr;
591 }
592 
595  m_validator_baton = nullptr;
596 }
597 
599  // If we have a validator callback, try to validate the callback
600  if (m_validator)
601  return m_validator(m_validator_baton, *this);
602  else
603  return true; // No validator, so response is valid
604 }
uint64_t m_index
When extracting data from a packet, this index will march along as things get extracted.
uint8_t GetHexU8(uint8_t fail_value=0, bool set_eof_on_fail=true)
#define PACKET_STARTS_WITH(s)
std::string m_packet
The string in which to extract data.
void SetResponseValidator(ResponseValidatorCallback callback, void *baton)
size_t GetHexByteString(std::string &str)
ResponseValidatorCallback m_validator
static llvm::raw_ostream & error(Stream &strm)
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:242
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)
llvm::StringRef GetStringRef() const
int void SetError(ValueType err, lldb::ErrorType type)
Set accessor with an error value and type.
Definition: Status.cpp:217
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:256
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