• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
9 #include "lldb/Utility/StringExtractorGDBRemote.h"
10 
11 #include <ctype.h>
12 #include <string.h>
13 
14 StringExtractorGDBRemote::ResponseType
GetResponseType() const15 StringExtractorGDBRemote::GetResponseType() const {
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 
53 StringExtractorGDBRemote::ServerPacketType
GetServerPacketType() const54 StringExtractorGDBRemote::GetServerPacketType() const {
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())
63     return eServerPacketType_invalid;
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 '%':
70     return eServerPacketType_notify;
71 
72   case '\x03':
73     if (packet_size == 1)
74       return eServerPacketType_interrupt;
75     break;
76 
77   case '-':
78     if (packet_size == 1)
79       return eServerPacketType_nack;
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:"))
95         return eServerPacketType_QEnvironment;
96       if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
97         return eServerPacketType_QEnvironmentHexEncoded;
98       if (PACKET_STARTS_WITH("QEnableErrorStrings"))
99         return eServerPacketType_QEnableErrorStrings;
100       break;
101 
102     case 'P':
103       if (PACKET_STARTS_WITH("QPassSignals:"))
104         return eServerPacketType_QPassSignals;
105       break;
106 
107     case 'S':
108       if (PACKET_MATCHES("QStartNoAckMode"))
109         return eServerPacketType_QStartNoAckMode;
110       if (PACKET_STARTS_WITH("QSaveRegisterState"))
111         return eServerPacketType_QSaveRegisterState;
112       if (PACKET_STARTS_WITH("QSetDisableASLR:"))
113         return eServerPacketType_QSetDisableASLR;
114       if (PACKET_STARTS_WITH("QSetDetachOnError:"))
115         return eServerPacketType_QSetDetachOnError;
116       if (PACKET_STARTS_WITH("QSetSTDIN:"))
117         return eServerPacketType_QSetSTDIN;
118       if (PACKET_STARTS_WITH("QSetSTDOUT:"))
119         return eServerPacketType_QSetSTDOUT;
120       if (PACKET_STARTS_WITH("QSetSTDERR:"))
121         return eServerPacketType_QSetSTDERR;
122       if (PACKET_STARTS_WITH("QSetWorkingDir:"))
123         return eServerPacketType_QSetWorkingDir;
124       if (PACKET_STARTS_WITH("QSetLogging:"))
125         return eServerPacketType_QSetLogging;
126       if (PACKET_STARTS_WITH("QSetMaxPacketSize:"))
127         return eServerPacketType_QSetMaxPacketSize;
128       if (PACKET_STARTS_WITH("QSetMaxPayloadSize:"))
129         return eServerPacketType_QSetMaxPayloadSize;
130       if (PACKET_STARTS_WITH("QSetEnableAsyncProfiling;"))
131         return eServerPacketType_QSetEnableAsyncProfiling;
132       if (PACKET_STARTS_WITH("QSyncThreadState:"))
133         return eServerPacketType_QSyncThreadState;
134       break;
135 
136     case 'L':
137       if (PACKET_STARTS_WITH("QLaunchArch:"))
138         return eServerPacketType_QLaunchArch;
139       if (PACKET_MATCHES("QListThreadsInStopReply"))
140         return eServerPacketType_QListThreadsInStopReply;
141       break;
142 
143     case 'R':
144       if (PACKET_STARTS_WITH("QRestoreRegisterState:"))
145         return eServerPacketType_QRestoreRegisterState;
146       break;
147 
148     case 'T':
149       if (PACKET_MATCHES("QThreadSuffixSupported"))
150         return eServerPacketType_QThreadSuffixSupported;
151       break;
152     }
153     break;
154 
155   case 'q':
156     switch (packet_cstr[1]) {
157     case 's':
158       if (PACKET_MATCHES("qsProcessInfo"))
159         return eServerPacketType_qsProcessInfo;
160       if (PACKET_MATCHES("qsThreadInfo"))
161         return eServerPacketType_qsThreadInfo;
162       break;
163 
164     case 'f':
165       if (PACKET_STARTS_WITH("qfProcessInfo"))
166         return eServerPacketType_qfProcessInfo;
167       if (PACKET_STARTS_WITH("qfThreadInfo"))
168         return eServerPacketType_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:"))
178         return eServerPacketType_qEcho;
179       break;
180 
181     case 'F':
182       if (PACKET_STARTS_WITH("qFileLoadAddress:"))
183         return eServerPacketType_qFileLoadAddress;
184       break;
185 
186     case 'G':
187       if (PACKET_STARTS_WITH("qGroupName:"))
188         return eServerPacketType_qGroupName;
189       if (PACKET_MATCHES("qGetWorkingDir"))
190         return eServerPacketType_qGetWorkingDir;
191       if (PACKET_MATCHES("qGetPid"))
192         return eServerPacketType_qGetPid;
193       if (PACKET_STARTS_WITH("qGetProfileData;"))
194         return eServerPacketType_qGetProfileData;
195       if (PACKET_MATCHES("qGDBServerVersion"))
196         return eServerPacketType_qGDBServerVersion;
197       break;
198 
199     case 'H':
200       if (PACKET_MATCHES("qHostInfo"))
201         return eServerPacketType_qHostInfo;
202       break;
203 
204     case 'K':
205       if (PACKET_STARTS_WITH("qKillSpawnedProcess"))
206         return eServerPacketType_qKillSpawnedProcess;
207       break;
208 
209     case 'L':
210       if (PACKET_STARTS_WITH("qLaunchGDBServer"))
211         return eServerPacketType_qLaunchGDBServer;
212       if (PACKET_MATCHES("qLaunchSuccess"))
213         return eServerPacketType_qLaunchSuccess;
214       break;
215 
216     case 'M':
217       if (PACKET_STARTS_WITH("qMemoryRegionInfo:"))
218         return eServerPacketType_qMemoryRegionInfo;
219       if (PACKET_MATCHES("qMemoryRegionInfo"))
220         return eServerPacketType_qMemoryRegionInfoSupported;
221       if (PACKET_STARTS_WITH("qModuleInfo:"))
222         return eServerPacketType_qModuleInfo;
223       break;
224 
225     case 'P':
226       if (PACKET_STARTS_WITH("qProcessInfoPID:"))
227         return eServerPacketType_qProcessInfoPID;
228       if (PACKET_STARTS_WITH("qPlatform_shell:"))
229         return eServerPacketType_qPlatform_shell;
230       if (PACKET_STARTS_WITH("qPlatform_mkdir:"))
231         return eServerPacketType_qPlatform_mkdir;
232       if (PACKET_STARTS_WITH("qPlatform_chmod:"))
233         return eServerPacketType_qPlatform_chmod;
234       if (PACKET_MATCHES("qProcessInfo"))
235         return eServerPacketType_qProcessInfo;
236       if (PACKET_STARTS_WITH("qPathComplete:"))
237         return eServerPacketType_qPathComplete;
238       break;
239 
240     case 'Q':
241       if (PACKET_MATCHES("qQueryGDBServer"))
242         return eServerPacketType_qQueryGDBServer;
243       break;
244 
245     case 'R':
246       if (PACKET_STARTS_WITH("qRcmd,"))
247         return eServerPacketType_qRcmd;
248       if (PACKET_STARTS_WITH("qRegisterInfo"))
249         return eServerPacketType_qRegisterInfo;
250       break;
251 
252     case 'S':
253       if (PACKET_STARTS_WITH("qSpeedTest:"))
254         return eServerPacketType_qSpeedTest;
255       if (PACKET_MATCHES("qShlibInfoAddr"))
256         return eServerPacketType_qShlibInfoAddr;
257       if (PACKET_MATCHES("qStepPacketSupported"))
258         return eServerPacketType_qStepPacketSupported;
259       if (PACKET_STARTS_WITH("qSupported"))
260         return eServerPacketType_qSupported;
261       if (PACKET_MATCHES("qSyncThreadStateSupported"))
262         return eServerPacketType_qSyncThreadStateSupported;
263       break;
264 
265     case 'T':
266       if (PACKET_STARTS_WITH("qThreadExtraInfo,"))
267         return eServerPacketType_qThreadExtraInfo;
268       if (PACKET_STARTS_WITH("qThreadStopInfo"))
269         return eServerPacketType_qThreadStopInfo;
270       break;
271 
272     case 'U':
273       if (PACKET_STARTS_WITH("qUserName:"))
274         return eServerPacketType_qUserName;
275       break;
276 
277     case 'V':
278       if (PACKET_MATCHES("qVAttachOrWaitSupported"))
279         return eServerPacketType_qVAttachOrWaitSupported;
280       break;
281 
282     case 'W':
283       if (PACKET_STARTS_WITH("qWatchpointSupportInfo:"))
284         return eServerPacketType_qWatchpointSupportInfo;
285       if (PACKET_MATCHES("qWatchpointSupportInfo"))
286         return eServerPacketType_qWatchpointSupportInfoSupported;
287       break;
288 
289     case 'X':
290       if (PACKET_STARTS_WITH("qXfer:"))
291         return eServerPacketType_qXfer;
292       break;
293     }
294     break;
295 
296   case 'j':
297     if (PACKET_STARTS_WITH("jModulesInfo:"))
298       return eServerPacketType_jModulesInfo;
299     if (PACKET_MATCHES("jSignalsInfo"))
300       return eServerPacketType_jSignalsInfo;
301     if (PACKET_MATCHES("jThreadsInfo"))
302       return eServerPacketType_jThreadsInfo;
303     if (PACKET_STARTS_WITH("jTraceBufferRead:"))
304       return eServerPacketType_jTraceBufferRead;
305     if (PACKET_STARTS_WITH("jTraceConfigRead:"))
306       return eServerPacketType_jTraceConfigRead;
307     if (PACKET_STARTS_WITH("jTraceMetaRead:"))
308       return eServerPacketType_jTraceMetaRead;
309     if (PACKET_STARTS_WITH("jTraceStart:"))
310       return eServerPacketType_jTraceStart;
311     if (PACKET_STARTS_WITH("jTraceStop:"))
312       return eServerPacketType_jTraceStop;
313     if (PACKET_MATCHES("jLLDBTraceSupportedType"))
314       return eServerPacketType_jLLDBTraceSupportedType;
315     break;
316 
317   case 'v':
318     if (PACKET_STARTS_WITH("vFile:")) {
319       if (PACKET_STARTS_WITH("vFile:open:"))
320         return eServerPacketType_vFile_open;
321       else if (PACKET_STARTS_WITH("vFile:close:"))
322         return eServerPacketType_vFile_close;
323       else if (PACKET_STARTS_WITH("vFile:pread"))
324         return eServerPacketType_vFile_pread;
325       else if (PACKET_STARTS_WITH("vFile:pwrite"))
326         return eServerPacketType_vFile_pwrite;
327       else if (PACKET_STARTS_WITH("vFile:size"))
328         return eServerPacketType_vFile_size;
329       else if (PACKET_STARTS_WITH("vFile:exists"))
330         return eServerPacketType_vFile_exists;
331       else if (PACKET_STARTS_WITH("vFile:stat"))
332         return eServerPacketType_vFile_stat;
333       else if (PACKET_STARTS_WITH("vFile:mode"))
334         return eServerPacketType_vFile_mode;
335       else if (PACKET_STARTS_WITH("vFile:MD5"))
336         return eServerPacketType_vFile_md5;
337       else if (PACKET_STARTS_WITH("vFile:symlink"))
338         return eServerPacketType_vFile_symlink;
339       else if (PACKET_STARTS_WITH("vFile:unlink"))
340         return eServerPacketType_vFile_unlink;
341 
342     } else {
343       if (PACKET_STARTS_WITH("vAttach;"))
344         return eServerPacketType_vAttach;
345       if (PACKET_STARTS_WITH("vAttachWait;"))
346         return eServerPacketType_vAttachWait;
347       if (PACKET_STARTS_WITH("vAttachOrWait;"))
348         return eServerPacketType_vAttachOrWait;
349       if (PACKET_STARTS_WITH("vAttachName;"))
350         return eServerPacketType_vAttachName;
351       if (PACKET_STARTS_WITH("vCont;"))
352         return eServerPacketType_vCont;
353       if (PACKET_MATCHES("vCont?"))
354         return eServerPacketType_vCont_actions;
355     }
356     break;
357   case '_':
358     switch (packet_cstr[1]) {
359     case 'M':
360       return eServerPacketType__M;
361 
362     case 'm':
363       return eServerPacketType__m;
364     }
365     break;
366 
367   case '?':
368     if (packet_size == 1)
369       return eServerPacketType_stop_reason;
370     break;
371 
372   case 'c':
373     return eServerPacketType_c;
374 
375   case 'C':
376     return eServerPacketType_C;
377 
378   case 'D':
379     if (packet_size == 1)
380       return eServerPacketType_D;
381     break;
382 
383   case 'g':
384     return eServerPacketType_g;
385 
386   case 'G':
387     return eServerPacketType_G;
388 
389   case 'H':
390     return eServerPacketType_H;
391 
392   case 'I':
393     return eServerPacketType_I;
394 
395   case 'k':
396     if (packet_size == 1)
397       return eServerPacketType_k;
398     break;
399 
400   case 'm':
401     return eServerPacketType_m;
402 
403   case 'M':
404     return eServerPacketType_M;
405 
406   case 'p':
407     return eServerPacketType_p;
408 
409   case 'P':
410     return eServerPacketType_P;
411 
412   case 's':
413     if (packet_size == 1)
414       return eServerPacketType_s;
415     break;
416 
417   case 'S':
418     return eServerPacketType_S;
419 
420   case 'x':
421     return eServerPacketType_x;
422 
423   case 'X':
424     return eServerPacketType_X;
425 
426   case 'T':
427     return eServerPacketType_T;
428 
429   case 'z':
430     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
431       return eServerPacketType_z;
432     break;
433 
434   case 'Z':
435     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
436       return eServerPacketType_Z;
437     break;
438   }
439   return eServerPacketType_unimplemented;
440 }
441 
IsOKResponse() const442 bool StringExtractorGDBRemote::IsOKResponse() const {
443   return GetResponseType() == eOK;
444 }
445 
IsUnsupportedResponse() const446 bool StringExtractorGDBRemote::IsUnsupportedResponse() const {
447   return GetResponseType() == eUnsupported;
448 }
449 
IsNormalResponse() const450 bool StringExtractorGDBRemote::IsNormalResponse() const {
451   return GetResponseType() == eResponse;
452 }
453 
IsErrorResponse() const454 bool StringExtractorGDBRemote::IsErrorResponse() const {
455   return GetResponseType() == eError && isxdigit(m_packet[1]) &&
456          isxdigit(m_packet[2]);
457 }
458 
GetError()459 uint8_t StringExtractorGDBRemote::GetError() {
460   if (GetResponseType() == eError) {
461     SetFilePos(1);
462     return GetHexU8(255);
463   }
464   return 0;
465 }
466 
GetStatus()467 lldb_private::Status StringExtractorGDBRemote::GetStatus() {
468   lldb_private::Status error;
469   if (GetResponseType() == eError) {
470     SetFilePos(1);
471     uint8_t errc = GetHexU8(255);
472     error.SetError(errc, lldb::eErrorTypeGeneric);
473 
474     error.SetErrorStringWithFormat("Error %u", errc);
475     std::string error_messg;
476     if (GetChar() == ';') {
477       GetHexByteString(error_messg);
478       error.SetErrorString(error_messg);
479     }
480   }
481   return error;
482 }
483 
GetEscapedBinaryData(std::string & str)484 size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
485   // Just get the data bytes in the string as
486   // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
487   // characters. If any 0x7d characters are left in the packet, then they are
488   // supposed to be there...
489   str.clear();
490   const size_t bytes_left = GetBytesLeft();
491   if (bytes_left > 0) {
492     str.assign(m_packet, m_index, bytes_left);
493     m_index += bytes_left;
494   }
495   return str.size();
496 }
497 
498 static bool
OKErrorNotSupportedResponseValidator(void *,const StringExtractorGDBRemote & response)499 OKErrorNotSupportedResponseValidator(void *,
500                                      const StringExtractorGDBRemote &response) {
501   switch (response.GetResponseType()) {
502   case StringExtractorGDBRemote::eOK:
503   case StringExtractorGDBRemote::eError:
504   case StringExtractorGDBRemote::eUnsupported:
505     return true;
506 
507   case StringExtractorGDBRemote::eAck:
508   case StringExtractorGDBRemote::eNack:
509   case StringExtractorGDBRemote::eResponse:
510     break;
511   }
512   return false;
513 }
514 
JSONResponseValidator(void *,const StringExtractorGDBRemote & response)515 static bool JSONResponseValidator(void *,
516                                   const StringExtractorGDBRemote &response) {
517   switch (response.GetResponseType()) {
518   case StringExtractorGDBRemote::eUnsupported:
519   case StringExtractorGDBRemote::eError:
520     return true; // Accept unsupported or EXX as valid responses
521 
522   case StringExtractorGDBRemote::eOK:
523   case StringExtractorGDBRemote::eAck:
524   case StringExtractorGDBRemote::eNack:
525     break;
526 
527   case StringExtractorGDBRemote::eResponse:
528     // JSON that is returned in from JSON query packets is currently always
529     // either a dictionary which starts with a '{', or an array which starts
530     // with a '['. This is a quick validator to just make sure the response
531     // could be valid JSON without having to validate all of the
532     // JSON content.
533     switch (response.GetStringRef()[0]) {
534     case '{':
535       return true;
536     case '[':
537       return true;
538     default:
539       break;
540     }
541     break;
542   }
543   return false;
544 }
545 
546 static bool
ASCIIHexBytesResponseValidator(void *,const StringExtractorGDBRemote & response)547 ASCIIHexBytesResponseValidator(void *,
548                                const StringExtractorGDBRemote &response) {
549   switch (response.GetResponseType()) {
550   case StringExtractorGDBRemote::eUnsupported:
551   case StringExtractorGDBRemote::eError:
552     return true; // Accept unsupported or EXX as valid responses
553 
554   case StringExtractorGDBRemote::eOK:
555   case StringExtractorGDBRemote::eAck:
556   case StringExtractorGDBRemote::eNack:
557     break;
558 
559   case StringExtractorGDBRemote::eResponse: {
560     uint32_t valid_count = 0;
561     for (const char ch : response.GetStringRef()) {
562       if (!isxdigit(ch)) {
563         return false;
564       }
565       if (++valid_count >= 16)
566         break; // Don't validate all the characters in case the packet is very
567                // large
568     }
569     return true;
570   } break;
571   }
572   return false;
573 }
574 
CopyResponseValidator(const StringExtractorGDBRemote & rhs)575 void StringExtractorGDBRemote::CopyResponseValidator(
576     const StringExtractorGDBRemote &rhs) {
577   m_validator = rhs.m_validator;
578   m_validator_baton = rhs.m_validator_baton;
579 }
580 
SetResponseValidator(ResponseValidatorCallback callback,void * baton)581 void StringExtractorGDBRemote::SetResponseValidator(
582     ResponseValidatorCallback callback, void *baton) {
583   m_validator = callback;
584   m_validator_baton = baton;
585 }
586 
SetResponseValidatorToOKErrorNotSupported()587 void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() {
588   m_validator = OKErrorNotSupportedResponseValidator;
589   m_validator_baton = nullptr;
590 }
591 
SetResponseValidatorToASCIIHexBytes()592 void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() {
593   m_validator = ASCIIHexBytesResponseValidator;
594   m_validator_baton = nullptr;
595 }
596 
SetResponseValidatorToJSON()597 void StringExtractorGDBRemote::SetResponseValidatorToJSON() {
598   m_validator = JSONResponseValidator;
599   m_validator_baton = nullptr;
600 }
601 
ValidateResponse() const602 bool StringExtractorGDBRemote::ValidateResponse() const {
603   // If we have a validator callback, try to validate the callback
604   if (m_validator)
605     return m_validator(m_validator_baton, *this);
606   else
607     return true; // No validator, so response is valid
608 }
609