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     break;
314 
315   case 'v':
316     if (PACKET_STARTS_WITH("vFile:")) {
317       if (PACKET_STARTS_WITH("vFile:open:"))
318         return eServerPacketType_vFile_open;
319       else if (PACKET_STARTS_WITH("vFile:close:"))
320         return eServerPacketType_vFile_close;
321       else if (PACKET_STARTS_WITH("vFile:pread"))
322         return eServerPacketType_vFile_pread;
323       else if (PACKET_STARTS_WITH("vFile:pwrite"))
324         return eServerPacketType_vFile_pwrite;
325       else if (PACKET_STARTS_WITH("vFile:size"))
326         return eServerPacketType_vFile_size;
327       else if (PACKET_STARTS_WITH("vFile:exists"))
328         return eServerPacketType_vFile_exists;
329       else if (PACKET_STARTS_WITH("vFile:stat"))
330         return eServerPacketType_vFile_stat;
331       else if (PACKET_STARTS_WITH("vFile:mode"))
332         return eServerPacketType_vFile_mode;
333       else if (PACKET_STARTS_WITH("vFile:MD5"))
334         return eServerPacketType_vFile_md5;
335       else if (PACKET_STARTS_WITH("vFile:symlink"))
336         return eServerPacketType_vFile_symlink;
337       else if (PACKET_STARTS_WITH("vFile:unlink"))
338         return eServerPacketType_vFile_unlink;
339 
340     } else {
341       if (PACKET_STARTS_WITH("vAttach;"))
342         return eServerPacketType_vAttach;
343       if (PACKET_STARTS_WITH("vAttachWait;"))
344         return eServerPacketType_vAttachWait;
345       if (PACKET_STARTS_WITH("vAttachOrWait;"))
346         return eServerPacketType_vAttachOrWait;
347       if (PACKET_STARTS_WITH("vAttachName;"))
348         return eServerPacketType_vAttachName;
349       if (PACKET_STARTS_WITH("vCont;"))
350         return eServerPacketType_vCont;
351       if (PACKET_MATCHES("vCont?"))
352         return eServerPacketType_vCont_actions;
353     }
354     break;
355   case '_':
356     switch (packet_cstr[1]) {
357     case 'M':
358       return eServerPacketType__M;
359 
360     case 'm':
361       return eServerPacketType__m;
362     }
363     break;
364 
365   case '?':
366     if (packet_size == 1)
367       return eServerPacketType_stop_reason;
368     break;
369 
370   case 'c':
371     return eServerPacketType_c;
372 
373   case 'C':
374     return eServerPacketType_C;
375 
376   case 'D':
377     if (packet_size == 1)
378       return eServerPacketType_D;
379     break;
380 
381   case 'g':
382     return eServerPacketType_g;
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   }
437   return eServerPacketType_unimplemented;
438 }
439 
IsOKResponse() const440 bool StringExtractorGDBRemote::IsOKResponse() const {
441   return GetResponseType() == eOK;
442 }
443 
IsUnsupportedResponse() const444 bool StringExtractorGDBRemote::IsUnsupportedResponse() const {
445   return GetResponseType() == eUnsupported;
446 }
447 
IsNormalResponse() const448 bool StringExtractorGDBRemote::IsNormalResponse() const {
449   return GetResponseType() == eResponse;
450 }
451 
IsErrorResponse() const452 bool StringExtractorGDBRemote::IsErrorResponse() const {
453   return GetResponseType() == eError && isxdigit(m_packet[1]) &&
454          isxdigit(m_packet[2]);
455 }
456 
GetError()457 uint8_t StringExtractorGDBRemote::GetError() {
458   if (GetResponseType() == eError) {
459     SetFilePos(1);
460     return GetHexU8(255);
461   }
462   return 0;
463 }
464 
GetStatus()465 lldb_private::Status StringExtractorGDBRemote::GetStatus() {
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 
GetEscapedBinaryData(std::string & str)482 size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
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
OKErrorNotSupportedResponseValidator(void *,const StringExtractorGDBRemote & response)497 OKErrorNotSupportedResponseValidator(void *,
498                                      const StringExtractorGDBRemote &response) {
499   switch (response.GetResponseType()) {
500   case StringExtractorGDBRemote::eOK:
501   case StringExtractorGDBRemote::eError:
502   case StringExtractorGDBRemote::eUnsupported:
503     return true;
504 
505   case StringExtractorGDBRemote::eAck:
506   case StringExtractorGDBRemote::eNack:
507   case StringExtractorGDBRemote::eResponse:
508     break;
509   }
510   return false;
511 }
512 
JSONResponseValidator(void *,const StringExtractorGDBRemote & response)513 static bool JSONResponseValidator(void *,
514                                   const StringExtractorGDBRemote &response) {
515   switch (response.GetResponseType()) {
516   case StringExtractorGDBRemote::eUnsupported:
517   case StringExtractorGDBRemote::eError:
518     return true; // Accept unsupported or EXX as valid responses
519 
520   case StringExtractorGDBRemote::eOK:
521   case StringExtractorGDBRemote::eAck:
522   case StringExtractorGDBRemote::eNack:
523     break;
524 
525   case StringExtractorGDBRemote::eResponse:
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
ASCIIHexBytesResponseValidator(void *,const StringExtractorGDBRemote & response)545 ASCIIHexBytesResponseValidator(void *,
546                                const StringExtractorGDBRemote &response) {
547   switch (response.GetResponseType()) {
548   case StringExtractorGDBRemote::eUnsupported:
549   case StringExtractorGDBRemote::eError:
550     return true; // Accept unsupported or EXX as valid responses
551 
552   case StringExtractorGDBRemote::eOK:
553   case StringExtractorGDBRemote::eAck:
554   case StringExtractorGDBRemote::eNack:
555     break;
556 
557   case StringExtractorGDBRemote::eResponse: {
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 
CopyResponseValidator(const StringExtractorGDBRemote & rhs)573 void StringExtractorGDBRemote::CopyResponseValidator(
574     const StringExtractorGDBRemote &rhs) {
575   m_validator = rhs.m_validator;
576   m_validator_baton = rhs.m_validator_baton;
577 }
578 
SetResponseValidator(ResponseValidatorCallback callback,void * baton)579 void StringExtractorGDBRemote::SetResponseValidator(
580     ResponseValidatorCallback callback, void *baton) {
581   m_validator = callback;
582   m_validator_baton = baton;
583 }
584 
SetResponseValidatorToOKErrorNotSupported()585 void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() {
586   m_validator = OKErrorNotSupportedResponseValidator;
587   m_validator_baton = nullptr;
588 }
589 
SetResponseValidatorToASCIIHexBytes()590 void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() {
591   m_validator = ASCIIHexBytesResponseValidator;
592   m_validator_baton = nullptr;
593 }
594 
SetResponseValidatorToJSON()595 void StringExtractorGDBRemote::SetResponseValidatorToJSON() {
596   m_validator = JSONResponseValidator;
597   m_validator_baton = nullptr;
598 }
599 
ValidateResponse() const600 bool StringExtractorGDBRemote::ValidateResponse() const {
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 }
607