xref: /llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp (revision 830c81d511881eae8be197d268e497d7fdf62e49)
1 //===-- StringExtractorGDBRemote.cpp ----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // C Includes
11 #include <string.h>
12 
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "Utility/StringExtractorGDBRemote.h"
17 #include "lldb/Utility/LLDBAssert.h"
18 
19 StringExtractorGDBRemote::ResponseType
20 StringExtractorGDBRemote::GetResponseType () const
21 {
22     if (m_packet.empty())
23         return eUnsupported;
24 
25     switch (m_packet[0])
26     {
27     case 'E':
28         if (m_packet.size() == 3 &&
29             isxdigit(m_packet[1]) &&
30             isxdigit(m_packet[2]))
31             return eError;
32         break;
33 
34     case 'O':
35         if (m_packet.size() == 2 && m_packet[1] == 'K')
36             return eOK;
37         break;
38 
39     case '+':
40         if (m_packet.size() == 1)
41             return eAck;
42         break;
43 
44     case '-':
45         if (m_packet.size() == 1)
46             return eNack;
47         break;
48     }
49     return eResponse;
50 }
51 
52 StringExtractorGDBRemote::ServerPacketType
53 StringExtractorGDBRemote::GetServerPacketType () const
54 {
55 #define PACKET_MATCHES(s) ((packet_size == (sizeof(s)-1)) && (strcmp((packet_cstr),(s)) == 0))
56 #define PACKET_STARTS_WITH(s) ((packet_size >= (sizeof(s)-1)) && ::strncmp(packet_cstr, s, (sizeof(s)-1))==0)
57 
58     // Empty is not a supported packet...
59     if (m_packet.empty())
60         return eServerPacketType_invalid;
61 
62     const size_t packet_size = m_packet.size();
63     const char *packet_cstr = m_packet.c_str();
64     switch (m_packet[0])
65     {
66 
67     case '%':
68         return eServerPacketType_notify;
69 
70     case '\x03':
71         if (packet_size == 1) return eServerPacketType_interrupt;
72         break;
73 
74     case '-':
75         if (packet_size == 1) return eServerPacketType_nack;
76         break;
77 
78     case '+':
79         if (packet_size == 1) return eServerPacketType_ack;
80         break;
81 
82     case 'A':
83         return eServerPacketType_A;
84 
85     case 'Q':
86 
87         switch (packet_cstr[1])
88         {
89         case 'E':
90             if (PACKET_STARTS_WITH ("QEnvironment:"))           return eServerPacketType_QEnvironment;
91             if (PACKET_STARTS_WITH ("QEnvironmentHexEncoded:")) return eServerPacketType_QEnvironmentHexEncoded;
92             break;
93 
94         case 'S':
95             if (PACKET_MATCHES ("QStartNoAckMode"))               return eServerPacketType_QStartNoAckMode;
96             if (PACKET_STARTS_WITH ("QSaveRegisterState"))        return eServerPacketType_QSaveRegisterState;
97             if (PACKET_STARTS_WITH ("QSetDisableASLR:"))          return eServerPacketType_QSetDisableASLR;
98             if (PACKET_STARTS_WITH ("QSetDetachOnError:"))        return eServerPacketType_QSetDetachOnError;
99             if (PACKET_STARTS_WITH ("QSetSTDIN:"))                return eServerPacketType_QSetSTDIN;
100             if (PACKET_STARTS_WITH ("QSetSTDOUT:"))               return eServerPacketType_QSetSTDOUT;
101             if (PACKET_STARTS_WITH ("QSetSTDERR:"))               return eServerPacketType_QSetSTDERR;
102             if (PACKET_STARTS_WITH ("QSetWorkingDir:"))           return eServerPacketType_QSetWorkingDir;
103             if (PACKET_STARTS_WITH ("QSetLogging:"))              return eServerPacketType_QSetLogging;
104             if (PACKET_STARTS_WITH ("QSetMaxPacketSize:"))        return eServerPacketType_QSetMaxPacketSize;
105             if (PACKET_STARTS_WITH ("QSetMaxPayloadSize:"))       return eServerPacketType_QSetMaxPayloadSize;
106             if (PACKET_STARTS_WITH ("QSetEnableAsyncProfiling;")) return eServerPacketType_QSetEnableAsyncProfiling;
107             if (PACKET_STARTS_WITH ("QSyncThreadState:"))         return eServerPacketType_QSyncThreadState;
108             break;
109 
110         case 'L':
111             if (PACKET_STARTS_WITH ("QLaunchArch:"))              return eServerPacketType_QLaunchArch;
112             if (PACKET_MATCHES("QListThreadsInStopReply"))        return eServerPacketType_QListThreadsInStopReply;
113             break;
114 
115         case 'R':
116             if (PACKET_STARTS_WITH ("QRestoreRegisterState:"))    return eServerPacketType_QRestoreRegisterState;
117             break;
118 
119         case 'T':
120             if (PACKET_MATCHES ("QThreadSuffixSupported"))        return eServerPacketType_QThreadSuffixSupported;
121             break;
122         }
123         break;
124 
125     case 'q':
126         switch (packet_cstr[1])
127         {
128         case 's':
129             if (PACKET_MATCHES ("qsProcessInfo"))               return eServerPacketType_qsProcessInfo;
130             if (PACKET_MATCHES ("qsThreadInfo"))                return eServerPacketType_qsThreadInfo;
131             break;
132 
133         case 'f':
134             if (PACKET_STARTS_WITH ("qfProcessInfo"))           return eServerPacketType_qfProcessInfo;
135             if (PACKET_STARTS_WITH ("qfThreadInfo"))            return eServerPacketType_qfThreadInfo;
136             break;
137 
138         case 'C':
139             if (packet_size == 2)                               return eServerPacketType_qC;
140             break;
141 
142         case 'E':
143             if (PACKET_STARTS_WITH ("qEcho:"))                  return eServerPacketType_qEcho;
144             break;
145 
146         case 'F':
147             if (PACKET_STARTS_WITH ("qFileLoadAddress:"))       return eServerPacketType_qFileLoadAddress;
148             break;
149 
150         case 'G':
151             if (PACKET_STARTS_WITH ("qGroupName:"))             return eServerPacketType_qGroupName;
152             if (PACKET_MATCHES ("qGetWorkingDir"))              return eServerPacketType_qGetWorkingDir;
153             if (PACKET_MATCHES ("qGetPid"))                     return eServerPacketType_qGetPid;
154             if (PACKET_STARTS_WITH ("qGetProfileData;"))        return eServerPacketType_qGetProfileData;
155             if (PACKET_MATCHES ("qGDBServerVersion"))           return eServerPacketType_qGDBServerVersion;
156             break;
157 
158         case 'H':
159             if (PACKET_MATCHES ("qHostInfo"))                   return eServerPacketType_qHostInfo;
160             break;
161 
162         case 'K':
163             if (PACKET_STARTS_WITH ("qKillSpawnedProcess"))     return eServerPacketType_qKillSpawnedProcess;
164             break;
165 
166         case 'L':
167             if (PACKET_STARTS_WITH ("qLaunchGDBServer"))        return eServerPacketType_qLaunchGDBServer;
168             if (PACKET_MATCHES ("qLaunchSuccess"))              return eServerPacketType_qLaunchSuccess;
169             break;
170 
171         case 'M':
172             if (PACKET_STARTS_WITH ("qMemoryRegionInfo:"))      return eServerPacketType_qMemoryRegionInfo;
173             if (PACKET_MATCHES ("qMemoryRegionInfo"))           return eServerPacketType_qMemoryRegionInfoSupported;
174             if (PACKET_STARTS_WITH ("qModuleInfo:"))             return eServerPacketType_qModuleInfo;
175             break;
176 
177         case 'P':
178             if (PACKET_STARTS_WITH ("qProcessInfoPID:"))        return eServerPacketType_qProcessInfoPID;
179             if (PACKET_STARTS_WITH ("qPlatform_shell:"))        return eServerPacketType_qPlatform_shell;
180             if (PACKET_STARTS_WITH ("qPlatform_mkdir:"))        return eServerPacketType_qPlatform_mkdir;
181             if (PACKET_STARTS_WITH ("qPlatform_chmod:"))        return eServerPacketType_qPlatform_chmod;
182             if (PACKET_MATCHES ("qProcessInfo"))                return eServerPacketType_qProcessInfo;
183             break;
184 
185         case 'Q':
186             if (PACKET_MATCHES ("qQueryGDBServer"))             return eServerPacketType_qQueryGDBServer;
187             break;
188 
189         case 'R':
190             if (PACKET_STARTS_WITH ("qRcmd,"))                  return eServerPacketType_qRcmd;
191             if (PACKET_STARTS_WITH ("qRegisterInfo"))           return eServerPacketType_qRegisterInfo;
192             break;
193 
194         case 'S':
195             if (PACKET_STARTS_WITH ("qSpeedTest:"))             return eServerPacketType_qSpeedTest;
196             if (PACKET_MATCHES ("qShlibInfoAddr"))              return eServerPacketType_qShlibInfoAddr;
197             if (PACKET_MATCHES ("qStepPacketSupported"))        return eServerPacketType_qStepPacketSupported;
198             if (PACKET_STARTS_WITH ("qSupported"))              return eServerPacketType_qSupported;
199             if (PACKET_MATCHES ("qSyncThreadStateSupported"))   return eServerPacketType_qSyncThreadStateSupported;
200             break;
201 
202         case 'T':
203             if (PACKET_STARTS_WITH ("qThreadExtraInfo,"))       return eServerPacketType_qThreadExtraInfo;
204             if (PACKET_STARTS_WITH ("qThreadStopInfo"))         return eServerPacketType_qThreadStopInfo;
205             break;
206 
207         case 'U':
208             if (PACKET_STARTS_WITH ("qUserName:"))              return eServerPacketType_qUserName;
209             break;
210 
211         case 'V':
212             if (PACKET_MATCHES ("qVAttachOrWaitSupported"))     return eServerPacketType_qVAttachOrWaitSupported;
213             break;
214 
215         case 'W':
216             if (PACKET_STARTS_WITH ("qWatchpointSupportInfo:")) return eServerPacketType_qWatchpointSupportInfo;
217             if (PACKET_MATCHES ("qWatchpointSupportInfo"))      return eServerPacketType_qWatchpointSupportInfoSupported;
218             break;
219 
220         case 'X':
221             if (PACKET_STARTS_WITH ("qXfer:auxv:read::"))       return eServerPacketType_qXfer_auxv_read;
222             break;
223         }
224         break;
225 
226     case 'j':
227         if (PACKET_MATCHES("jSignalsInfo"))                     return eServerPacketType_jSignalsInfo;
228         if (PACKET_MATCHES("jThreadsInfo"))                     return eServerPacketType_jThreadsInfo;
229         break;
230 
231     case 'v':
232             if (PACKET_STARTS_WITH("vFile:"))
233             {
234                 if (PACKET_STARTS_WITH("vFile:open:"))          return eServerPacketType_vFile_open;
235                 else if (PACKET_STARTS_WITH("vFile:close:"))    return eServerPacketType_vFile_close;
236                 else if (PACKET_STARTS_WITH("vFile:pread"))     return eServerPacketType_vFile_pread;
237                 else if (PACKET_STARTS_WITH("vFile:pwrite"))    return eServerPacketType_vFile_pwrite;
238                 else if (PACKET_STARTS_WITH("vFile:size"))      return eServerPacketType_vFile_size;
239                 else if (PACKET_STARTS_WITH("vFile:exists"))    return eServerPacketType_vFile_exists;
240                 else if (PACKET_STARTS_WITH("vFile:stat"))      return eServerPacketType_vFile_stat;
241                 else if (PACKET_STARTS_WITH("vFile:mode"))      return eServerPacketType_vFile_mode;
242                 else if (PACKET_STARTS_WITH("vFile:MD5"))       return eServerPacketType_vFile_md5;
243                 else if (PACKET_STARTS_WITH("vFile:symlink"))   return eServerPacketType_vFile_symlink;
244                 else if (PACKET_STARTS_WITH("vFile:unlink"))    return eServerPacketType_vFile_unlink;
245 
246             } else {
247               if (PACKET_STARTS_WITH ("vAttach;"))              return eServerPacketType_vAttach;
248               if (PACKET_STARTS_WITH ("vAttachWait;"))          return eServerPacketType_vAttachWait;
249               if (PACKET_STARTS_WITH ("vAttachOrWait;"))        return eServerPacketType_vAttachOrWait;
250               if (PACKET_STARTS_WITH ("vAttachName;"))          return eServerPacketType_vAttachName;
251               if (PACKET_STARTS_WITH("vCont;"))                 return eServerPacketType_vCont;
252               if (PACKET_MATCHES ("vCont?"))                    return eServerPacketType_vCont_actions;
253             }
254             break;
255       case '_':
256         switch (packet_cstr[1])
257         {
258         case 'M':
259             return eServerPacketType__M;
260 
261         case 'm':
262             return eServerPacketType__m;
263         }
264         break;
265 
266       case '?':
267         if (packet_size == 1) return eServerPacketType_stop_reason;
268         break;
269 
270       case 'c':
271         return eServerPacketType_c;
272 
273       case 'C':
274         return eServerPacketType_C;
275 
276       case 'D':
277         if (packet_size == 1) return eServerPacketType_D;
278         break;
279 
280       case 'g':
281         if (packet_size == 1) return eServerPacketType_g;
282         break;
283 
284       case 'G':
285         return eServerPacketType_G;
286 
287       case 'H':
288         return eServerPacketType_H;
289 
290       case 'I':
291         return eServerPacketType_I;
292 
293       case 'k':
294         if (packet_size == 1) return eServerPacketType_k;
295         break;
296 
297       case 'm':
298         return eServerPacketType_m;
299 
300       case 'M':
301         return eServerPacketType_M;
302 
303       case 'p':
304         return eServerPacketType_p;
305 
306       case 'P':
307         return eServerPacketType_P;
308 
309       case 's':
310         if (packet_size == 1) return eServerPacketType_s;
311         break;
312 
313       case 'S':
314         return eServerPacketType_S;
315 
316       case 'x':
317         return eServerPacketType_x;
318 
319       case 'X':
320         return eServerPacketType_X;
321 
322       case 'T':
323         return eServerPacketType_T;
324 
325       case 'z':
326         if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
327           return eServerPacketType_z;
328         break;
329 
330       case 'Z':
331         if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
332           return eServerPacketType_Z;
333         break;
334     }
335     return eServerPacketType_unimplemented;
336 }
337 
338 bool
339 StringExtractorGDBRemote::IsOKResponse() const
340 {
341     return GetResponseType () == eOK;
342 }
343 
344 
345 bool
346 StringExtractorGDBRemote::IsUnsupportedResponse() const
347 {
348     return GetResponseType () == eUnsupported;
349 }
350 
351 bool
352 StringExtractorGDBRemote::IsNormalResponse() const
353 {
354     return GetResponseType () == eResponse;
355 }
356 
357 bool
358 StringExtractorGDBRemote::IsErrorResponse() const
359 {
360     return GetResponseType () == eError &&
361            m_packet.size() == 3 &&
362            isxdigit(m_packet[1]) &&
363            isxdigit(m_packet[2]);
364 }
365 
366 uint8_t
367 StringExtractorGDBRemote::GetError ()
368 {
369     if (GetResponseType() == eError)
370     {
371         SetFilePos(1);
372         return GetHexU8(255);
373     }
374     return 0;
375 }
376 
377 size_t
378 StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str)
379 {
380     // Just get the data bytes in the string as GDBRemoteCommunication::CheckForPacket()
381     // already removes any 0x7d escaped characters. If any 0x7d characters are left in
382     // the packet, then they are supposed to be there...
383     str.clear();
384     const size_t bytes_left = GetBytesLeft();
385     if (bytes_left > 0)
386     {
387         str.assign(m_packet, m_index, bytes_left);
388         m_index += bytes_left;
389     }
390     return str.size();
391 }
392 
393 static bool
394 OKErrorNotSupportedResponseValidator(void *, const StringExtractorGDBRemote &response)
395 {
396     switch (response.GetResponseType())
397     {
398         case StringExtractorGDBRemote::eOK:
399         case StringExtractorGDBRemote::eError:
400         case StringExtractorGDBRemote::eUnsupported:
401             return true;
402 
403         case StringExtractorGDBRemote::eAck:
404         case StringExtractorGDBRemote::eNack:
405         case StringExtractorGDBRemote::eResponse:
406             break;
407     }
408     lldbassert(!"Packet validatation failed, check why this is happening");
409     return false;
410 }
411 
412 static bool
413 JSONResponseValidator(void *, const StringExtractorGDBRemote &response)
414 {
415     switch (response.GetResponseType())
416     {
417         case StringExtractorGDBRemote::eUnsupported:
418         case StringExtractorGDBRemote::eError:
419             return true; // Accept unsupported or EXX as valid responses
420 
421         case StringExtractorGDBRemote::eOK:
422         case StringExtractorGDBRemote::eAck:
423         case StringExtractorGDBRemote::eNack:
424             break;
425 
426         case StringExtractorGDBRemote::eResponse:
427             // JSON that is returned in from JSON query packets is currently always
428             // either a dictionary which starts with a '{', or an array which
429             // starts with a '['. This is a quick validator to just make sure the
430             // response could be valid JSON without having to validate all of the
431             // JSON content.
432             switch (response.GetStringRef()[0])
433             {
434                 case '{': return true;
435                 case '[': return true;
436                 default:
437                     break;
438             }
439             break;
440     }
441     lldbassert(!"Packet validatation failed, check why this is happening");
442     return false;
443 }
444 
445 static bool
446 ASCIIHexBytesResponseValidator(void *, const StringExtractorGDBRemote &response)
447 {
448     switch (response.GetResponseType())
449     {
450         case StringExtractorGDBRemote::eUnsupported:
451         case StringExtractorGDBRemote::eError:
452             return true; // Accept unsupported or EXX as valid responses
453 
454         case StringExtractorGDBRemote::eOK:
455         case StringExtractorGDBRemote::eAck:
456         case StringExtractorGDBRemote::eNack:
457             break;
458 
459         case StringExtractorGDBRemote::eResponse:
460             {
461                 uint32_t valid_count = 0;
462                 for (const char ch : response.GetStringRef())
463                 {
464                     if (!isxdigit(ch))
465                     {
466                         lldbassert(!"Packet validatation failed, check why this is happening");
467                         return false;
468                     }
469                     if (++valid_count >= 16)
470                         break; // Don't validate all the characters in case the packet is very large
471                 }
472                 return true;
473             }
474             break;
475     }
476     lldbassert(!"Packet validatation failed, check why this is happening");
477     return false;
478 }
479 
480 void
481 StringExtractorGDBRemote::CopyResponseValidator(const StringExtractorGDBRemote& rhs)
482 {
483     m_validator = rhs.m_validator;
484     m_validator_baton = rhs.m_validator_baton;
485 }
486 
487 void
488 StringExtractorGDBRemote::SetResponseValidator(ResponseValidatorCallback callback, void *baton)
489 {
490     m_validator = callback;
491     m_validator_baton = baton;
492 }
493 
494 void
495 StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported()
496 {
497     m_validator = OKErrorNotSupportedResponseValidator;
498     m_validator_baton = nullptr;
499 }
500 
501 void
502 StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes()
503 {
504     m_validator = ASCIIHexBytesResponseValidator;
505     m_validator_baton = nullptr;
506 }
507 
508 void
509 StringExtractorGDBRemote::SetResponseValidatorToJSON()
510 {
511     m_validator = JSONResponseValidator;
512     m_validator_baton = nullptr;
513 }
514 
515 bool
516 StringExtractorGDBRemote::ValidateResponse() const
517 {
518     // If we have a validator callback, try to validate the callback
519     if (m_validator)
520         return m_validator(m_validator_baton, *this);
521     else
522         return true; // No validator, so response is valid
523 }
524 
525 
526