xref: /llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp (revision bff4673b41781ec5bff6b96b52cf321d2271726c)
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 <cctype>
12 #include <cstring>
13 
14 constexpr lldb::pid_t StringExtractorGDBRemote::AllProcesses;
15 constexpr lldb::tid_t StringExtractorGDBRemote::AllThreads;
16 
17 StringExtractorGDBRemote::ResponseType
18 StringExtractorGDBRemote::GetResponseType() const {
19   if (m_packet.empty())
20     return eUnsupported;
21 
22   switch (m_packet[0]) {
23   case 'E':
24     if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) {
25       if (m_packet.size() == 3)
26         return eError;
27       llvm::StringRef packet_ref(m_packet);
28       if (packet_ref[3] == ';') {
29         auto err_string = packet_ref.substr(4);
30         for (auto e : err_string)
31           if (!isxdigit(e))
32             return eResponse;
33         return eError;
34       }
35     }
36     break;
37 
38   case 'O':
39     if (m_packet.size() == 2 && m_packet[1] == 'K')
40       return eOK;
41     break;
42 
43   case '+':
44     if (m_packet.size() == 1)
45       return eAck;
46     break;
47 
48   case '-':
49     if (m_packet.size() == 1)
50       return eNack;
51     break;
52   }
53   return eResponse;
54 }
55 
56 StringExtractorGDBRemote::ServerPacketType
57 StringExtractorGDBRemote::GetServerPacketType() const {
58 #define PACKET_MATCHES(s)                                                      \
59   ((packet_size == (sizeof(s) - 1)) && (strcmp((packet_cstr), (s)) == 0))
60 #define PACKET_STARTS_WITH(s)                                                  \
61   ((packet_size >= (sizeof(s) - 1)) &&                                         \
62    ::strncmp(packet_cstr, s, (sizeof(s) - 1)) == 0)
63 
64   // Empty is not a supported packet...
65   if (m_packet.empty())
66     return eServerPacketType_invalid;
67 
68   const size_t packet_size = m_packet.size();
69   const char *packet_cstr = m_packet.c_str();
70   switch (m_packet[0]) {
71 
72   case '%':
73     return eServerPacketType_notify;
74 
75   case '\x03':
76     if (packet_size == 1)
77       return eServerPacketType_interrupt;
78     break;
79 
80   case '-':
81     if (packet_size == 1)
82       return eServerPacketType_nack;
83     break;
84 
85   case '+':
86     if (packet_size == 1)
87       return eServerPacketType_ack;
88     break;
89 
90   case 'A':
91     return eServerPacketType_A;
92 
93   case 'Q':
94 
95     switch (packet_cstr[1]) {
96     case 'E':
97       if (PACKET_STARTS_WITH("QEnvironment:"))
98         return eServerPacketType_QEnvironment;
99       if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
100         return eServerPacketType_QEnvironmentHexEncoded;
101       if (PACKET_STARTS_WITH("QEnableErrorStrings"))
102         return eServerPacketType_QEnableErrorStrings;
103       break;
104 
105     case 'P':
106       if (PACKET_STARTS_WITH("QPassSignals:"))
107         return eServerPacketType_QPassSignals;
108       break;
109 
110     case 'S':
111       if (PACKET_MATCHES("QStartNoAckMode"))
112         return eServerPacketType_QStartNoAckMode;
113       if (PACKET_STARTS_WITH("QSaveRegisterState"))
114         return eServerPacketType_QSaveRegisterState;
115       if (PACKET_STARTS_WITH("QSetDisableASLR:"))
116         return eServerPacketType_QSetDisableASLR;
117       if (PACKET_STARTS_WITH("QSetDetachOnError:"))
118         return eServerPacketType_QSetDetachOnError;
119       if (PACKET_STARTS_WITH("QSetSTDIN:"))
120         return eServerPacketType_QSetSTDIN;
121       if (PACKET_STARTS_WITH("QSetSTDOUT:"))
122         return eServerPacketType_QSetSTDOUT;
123       if (PACKET_STARTS_WITH("QSetSTDERR:"))
124         return eServerPacketType_QSetSTDERR;
125       if (PACKET_STARTS_WITH("QSetWorkingDir:"))
126         return eServerPacketType_QSetWorkingDir;
127       if (PACKET_STARTS_WITH("QSetLogging:"))
128         return eServerPacketType_QSetLogging;
129       if (PACKET_STARTS_WITH("QSetIgnoredExceptions"))
130         return eServerPacketType_QSetIgnoredExceptions;
131       if (PACKET_STARTS_WITH("QSetMaxPacketSize:"))
132         return eServerPacketType_QSetMaxPacketSize;
133       if (PACKET_STARTS_WITH("QSetMaxPayloadSize:"))
134         return eServerPacketType_QSetMaxPayloadSize;
135       if (PACKET_STARTS_WITH("QSetEnableAsyncProfiling;"))
136         return eServerPacketType_QSetEnableAsyncProfiling;
137       if (PACKET_STARTS_WITH("QSyncThreadState:"))
138         return eServerPacketType_QSyncThreadState;
139       break;
140 
141     case 'L':
142       if (PACKET_STARTS_WITH("QLaunchArch:"))
143         return eServerPacketType_QLaunchArch;
144       if (PACKET_MATCHES("QListThreadsInStopReply"))
145         return eServerPacketType_QListThreadsInStopReply;
146       break;
147 
148     case 'M':
149       if (PACKET_STARTS_WITH("QMemTags"))
150         return eServerPacketType_QMemTags;
151       break;
152 
153     case 'R':
154       if (PACKET_STARTS_WITH("QRestoreRegisterState:"))
155         return eServerPacketType_QRestoreRegisterState;
156       break;
157 
158     case 'T':
159       if (PACKET_MATCHES("QThreadSuffixSupported"))
160         return eServerPacketType_QThreadSuffixSupported;
161       break;
162     }
163     break;
164 
165   case 'q':
166     switch (packet_cstr[1]) {
167     case 's':
168       if (PACKET_MATCHES("qsProcessInfo"))
169         return eServerPacketType_qsProcessInfo;
170       if (PACKET_MATCHES("qsThreadInfo"))
171         return eServerPacketType_qsThreadInfo;
172       break;
173 
174     case 'f':
175       if (PACKET_STARTS_WITH("qfProcessInfo"))
176         return eServerPacketType_qfProcessInfo;
177       if (PACKET_STARTS_WITH("qfThreadInfo"))
178         return eServerPacketType_qfThreadInfo;
179       break;
180 
181     case 'C':
182       if (packet_size == 2)
183         return eServerPacketType_qC;
184       break;
185 
186     case 'E':
187       if (PACKET_STARTS_WITH("qEcho:"))
188         return eServerPacketType_qEcho;
189       break;
190 
191     case 'F':
192       if (PACKET_STARTS_WITH("qFileLoadAddress:"))
193         return eServerPacketType_qFileLoadAddress;
194       break;
195 
196     case 'G':
197       if (PACKET_STARTS_WITH("qGroupName:"))
198         return eServerPacketType_qGroupName;
199       if (PACKET_MATCHES("qGetWorkingDir"))
200         return eServerPacketType_qGetWorkingDir;
201       if (PACKET_MATCHES("qGetPid"))
202         return eServerPacketType_qGetPid;
203       if (PACKET_STARTS_WITH("qGetProfileData;"))
204         return eServerPacketType_qGetProfileData;
205       if (PACKET_MATCHES("qGDBServerVersion"))
206         return eServerPacketType_qGDBServerVersion;
207       break;
208 
209     case 'H':
210       if (PACKET_MATCHES("qHostInfo"))
211         return eServerPacketType_qHostInfo;
212       break;
213 
214     case 'K':
215       if (PACKET_STARTS_WITH("qKillSpawnedProcess"))
216         return eServerPacketType_qKillSpawnedProcess;
217       break;
218 
219     case 'L':
220       if (PACKET_STARTS_WITH("qLaunchGDBServer"))
221         return eServerPacketType_qLaunchGDBServer;
222       if (PACKET_MATCHES("qLaunchSuccess"))
223         return eServerPacketType_qLaunchSuccess;
224       break;
225 
226     case 'M':
227       if (PACKET_STARTS_WITH("qMemoryRegionInfo:"))
228         return eServerPacketType_qMemoryRegionInfo;
229       if (PACKET_MATCHES("qMemoryRegionInfo"))
230         return eServerPacketType_qMemoryRegionInfoSupported;
231       if (PACKET_STARTS_WITH("qModuleInfo:"))
232         return eServerPacketType_qModuleInfo;
233       if (PACKET_STARTS_WITH("qMemTags:"))
234         return eServerPacketType_qMemTags;
235       break;
236 
237     case 'P':
238       if (PACKET_STARTS_WITH("qProcessInfoPID:"))
239         return eServerPacketType_qProcessInfoPID;
240       if (PACKET_STARTS_WITH("qPlatform_shell:"))
241         return eServerPacketType_qPlatform_shell;
242       if (PACKET_STARTS_WITH("qPlatform_mkdir:"))
243         return eServerPacketType_qPlatform_mkdir;
244       if (PACKET_STARTS_WITH("qPlatform_chmod:"))
245         return eServerPacketType_qPlatform_chmod;
246       if (PACKET_MATCHES("qProcessInfo"))
247         return eServerPacketType_qProcessInfo;
248       if (PACKET_STARTS_WITH("qPathComplete:"))
249         return eServerPacketType_qPathComplete;
250       break;
251 
252     case 'Q':
253       if (PACKET_MATCHES("qQueryGDBServer"))
254         return eServerPacketType_qQueryGDBServer;
255       break;
256 
257     case 'R':
258       if (PACKET_STARTS_WITH("qRcmd,"))
259         return eServerPacketType_qRcmd;
260       if (PACKET_STARTS_WITH("qRegisterInfo"))
261         return eServerPacketType_qRegisterInfo;
262       break;
263 
264     case 'S':
265       if (PACKET_STARTS_WITH("qSaveCore"))
266         return eServerPacketType_qLLDBSaveCore;
267       if (PACKET_STARTS_WITH("qSpeedTest:"))
268         return eServerPacketType_qSpeedTest;
269       if (PACKET_MATCHES("qShlibInfoAddr"))
270         return eServerPacketType_qShlibInfoAddr;
271       if (PACKET_MATCHES("qStepPacketSupported"))
272         return eServerPacketType_qStepPacketSupported;
273       if (PACKET_STARTS_WITH("qSupported"))
274         return eServerPacketType_qSupported;
275       if (PACKET_MATCHES("qSyncThreadStateSupported"))
276         return eServerPacketType_qSyncThreadStateSupported;
277       break;
278 
279     case 'T':
280       if (PACKET_STARTS_WITH("qThreadExtraInfo,"))
281         return eServerPacketType_qThreadExtraInfo;
282       if (PACKET_STARTS_WITH("qThreadStopInfo"))
283         return eServerPacketType_qThreadStopInfo;
284       break;
285 
286     case 'U':
287       if (PACKET_STARTS_WITH("qUserName:"))
288         return eServerPacketType_qUserName;
289       break;
290 
291     case 'V':
292       if (PACKET_MATCHES("qVAttachOrWaitSupported"))
293         return eServerPacketType_qVAttachOrWaitSupported;
294       break;
295 
296     case 'W':
297       if (PACKET_STARTS_WITH("qWatchpointSupportInfo:"))
298         return eServerPacketType_qWatchpointSupportInfo;
299       if (PACKET_MATCHES("qWatchpointSupportInfo"))
300         return eServerPacketType_qWatchpointSupportInfoSupported;
301       break;
302 
303     case 'X':
304       if (PACKET_STARTS_WITH("qXfer:"))
305         return eServerPacketType_qXfer;
306       break;
307     }
308     break;
309 
310   case 'j':
311     if (PACKET_STARTS_WITH("jModulesInfo:"))
312       return eServerPacketType_jModulesInfo;
313     if (PACKET_MATCHES("jSignalsInfo"))
314       return eServerPacketType_jSignalsInfo;
315     if (PACKET_MATCHES("jThreadsInfo"))
316       return eServerPacketType_jThreadsInfo;
317 
318     if (PACKET_MATCHES("jLLDBTraceSupported"))
319       return eServerPacketType_jLLDBTraceSupported;
320     if (PACKET_STARTS_WITH("jLLDBTraceStop:"))
321       return eServerPacketType_jLLDBTraceStop;
322     if (PACKET_STARTS_WITH("jLLDBTraceStart:"))
323       return eServerPacketType_jLLDBTraceStart;
324     if (PACKET_STARTS_WITH("jLLDBTraceGetState:"))
325       return eServerPacketType_jLLDBTraceGetState;
326     if (PACKET_STARTS_WITH("jLLDBTraceGetBinaryData:"))
327       return eServerPacketType_jLLDBTraceGetBinaryData;
328     break;
329 
330   case 'v':
331     if (PACKET_STARTS_WITH("vFile:")) {
332       if (PACKET_STARTS_WITH("vFile:open:"))
333         return eServerPacketType_vFile_open;
334       else if (PACKET_STARTS_WITH("vFile:close:"))
335         return eServerPacketType_vFile_close;
336       else if (PACKET_STARTS_WITH("vFile:pread"))
337         return eServerPacketType_vFile_pread;
338       else if (PACKET_STARTS_WITH("vFile:pwrite"))
339         return eServerPacketType_vFile_pwrite;
340       else if (PACKET_STARTS_WITH("vFile:size"))
341         return eServerPacketType_vFile_size;
342       else if (PACKET_STARTS_WITH("vFile:exists"))
343         return eServerPacketType_vFile_exists;
344       else if (PACKET_STARTS_WITH("vFile:fstat"))
345         return eServerPacketType_vFile_fstat;
346       else if (PACKET_STARTS_WITH("vFile:stat"))
347         return eServerPacketType_vFile_stat;
348       else if (PACKET_STARTS_WITH("vFile:mode"))
349         return eServerPacketType_vFile_mode;
350       else if (PACKET_STARTS_WITH("vFile:MD5"))
351         return eServerPacketType_vFile_md5;
352       else if (PACKET_STARTS_WITH("vFile:symlink"))
353         return eServerPacketType_vFile_symlink;
354       else if (PACKET_STARTS_WITH("vFile:unlink"))
355         return eServerPacketType_vFile_unlink;
356 
357     } else {
358       if (PACKET_STARTS_WITH("vAttach;"))
359         return eServerPacketType_vAttach;
360       if (PACKET_STARTS_WITH("vAttachWait;"))
361         return eServerPacketType_vAttachWait;
362       if (PACKET_STARTS_WITH("vAttachOrWait;"))
363         return eServerPacketType_vAttachOrWait;
364       if (PACKET_STARTS_WITH("vAttachName;"))
365         return eServerPacketType_vAttachName;
366       if (PACKET_STARTS_WITH("vCont;"))
367         return eServerPacketType_vCont;
368       if (PACKET_MATCHES("vCont?"))
369         return eServerPacketType_vCont_actions;
370       if (PACKET_STARTS_WITH("vRun;"))
371         return eServerPacketType_vRun;
372     }
373     break;
374   case '_':
375     switch (packet_cstr[1]) {
376     case 'M':
377       return eServerPacketType__M;
378 
379     case 'm':
380       return eServerPacketType__m;
381     }
382     break;
383 
384   case '?':
385     if (packet_size == 1)
386       return eServerPacketType_stop_reason;
387     break;
388 
389   case 'c':
390     return eServerPacketType_c;
391 
392   case 'C':
393     return eServerPacketType_C;
394 
395   case 'D':
396     return eServerPacketType_D;
397 
398   case 'g':
399     return eServerPacketType_g;
400 
401   case 'G':
402     return eServerPacketType_G;
403 
404   case 'H':
405     return eServerPacketType_H;
406 
407   case 'I':
408     return eServerPacketType_I;
409 
410   case 'k':
411     if (packet_size == 1)
412       return eServerPacketType_k;
413     break;
414 
415   case 'm':
416     return eServerPacketType_m;
417 
418   case 'M':
419     return eServerPacketType_M;
420 
421   case 'p':
422     return eServerPacketType_p;
423 
424   case 'P':
425     return eServerPacketType_P;
426 
427   case 's':
428     if (packet_size == 1)
429       return eServerPacketType_s;
430     break;
431 
432   case 'S':
433     return eServerPacketType_S;
434 
435   case 'x':
436     return eServerPacketType_x;
437 
438   case 'X':
439     return eServerPacketType_X;
440 
441   case 'T':
442     return eServerPacketType_T;
443 
444   case 'z':
445     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
446       return eServerPacketType_z;
447     break;
448 
449   case 'Z':
450     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
451       return eServerPacketType_Z;
452     break;
453   }
454   return eServerPacketType_unimplemented;
455 }
456 
457 bool StringExtractorGDBRemote::IsOKResponse() const {
458   return GetResponseType() == eOK;
459 }
460 
461 bool StringExtractorGDBRemote::IsUnsupportedResponse() const {
462   return GetResponseType() == eUnsupported;
463 }
464 
465 bool StringExtractorGDBRemote::IsNormalResponse() const {
466   return GetResponseType() == eResponse;
467 }
468 
469 bool StringExtractorGDBRemote::IsErrorResponse() const {
470   return GetResponseType() == eError && isxdigit(m_packet[1]) &&
471          isxdigit(m_packet[2]);
472 }
473 
474 uint8_t StringExtractorGDBRemote::GetError() {
475   if (GetResponseType() == eError) {
476     SetFilePos(1);
477     return GetHexU8(255);
478   }
479   return 0;
480 }
481 
482 lldb_private::Status StringExtractorGDBRemote::GetStatus() {
483   lldb_private::Status error;
484   if (GetResponseType() == eError) {
485     SetFilePos(1);
486     uint8_t errc = GetHexU8(255);
487     error.SetError(errc, lldb::eErrorTypeGeneric);
488 
489     error.SetErrorStringWithFormat("Error %u", errc);
490     std::string error_messg;
491     if (GetChar() == ';') {
492       GetHexByteString(error_messg);
493       error.SetErrorString(error_messg);
494     }
495   }
496   return error;
497 }
498 
499 size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
500   // Just get the data bytes in the string as
501   // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
502   // characters. If any 0x7d characters are left in the packet, then they are
503   // supposed to be there...
504   str.clear();
505   const size_t bytes_left = GetBytesLeft();
506   if (bytes_left > 0) {
507     str.assign(m_packet, m_index, bytes_left);
508     m_index += bytes_left;
509   }
510   return str.size();
511 }
512 
513 static bool
514 OKErrorNotSupportedResponseValidator(void *,
515                                      const StringExtractorGDBRemote &response) {
516   switch (response.GetResponseType()) {
517   case StringExtractorGDBRemote::eOK:
518   case StringExtractorGDBRemote::eError:
519   case StringExtractorGDBRemote::eUnsupported:
520     return true;
521 
522   case StringExtractorGDBRemote::eAck:
523   case StringExtractorGDBRemote::eNack:
524   case StringExtractorGDBRemote::eResponse:
525     break;
526   }
527   return false;
528 }
529 
530 static bool JSONResponseValidator(void *,
531                                   const StringExtractorGDBRemote &response) {
532   switch (response.GetResponseType()) {
533   case StringExtractorGDBRemote::eUnsupported:
534   case StringExtractorGDBRemote::eError:
535     return true; // Accept unsupported or EXX as valid responses
536 
537   case StringExtractorGDBRemote::eOK:
538   case StringExtractorGDBRemote::eAck:
539   case StringExtractorGDBRemote::eNack:
540     break;
541 
542   case StringExtractorGDBRemote::eResponse:
543     // JSON that is returned in from JSON query packets is currently always
544     // either a dictionary which starts with a '{', or an array which starts
545     // with a '['. This is a quick validator to just make sure the response
546     // could be valid JSON without having to validate all of the
547     // JSON content.
548     switch (response.GetStringRef()[0]) {
549     case '{':
550       return true;
551     case '[':
552       return true;
553     default:
554       break;
555     }
556     break;
557   }
558   return false;
559 }
560 
561 static bool
562 ASCIIHexBytesResponseValidator(void *,
563                                const StringExtractorGDBRemote &response) {
564   switch (response.GetResponseType()) {
565   case StringExtractorGDBRemote::eUnsupported:
566   case StringExtractorGDBRemote::eError:
567     return true; // Accept unsupported or EXX as valid responses
568 
569   case StringExtractorGDBRemote::eOK:
570   case StringExtractorGDBRemote::eAck:
571   case StringExtractorGDBRemote::eNack:
572     break;
573 
574   case StringExtractorGDBRemote::eResponse: {
575     uint32_t valid_count = 0;
576     for (const char ch : response.GetStringRef()) {
577       if (!isxdigit(ch)) {
578         return false;
579       }
580       if (++valid_count >= 16)
581         break; // Don't validate all the characters in case the packet is very
582                // large
583     }
584     return true;
585   } break;
586   }
587   return false;
588 }
589 
590 void StringExtractorGDBRemote::CopyResponseValidator(
591     const StringExtractorGDBRemote &rhs) {
592   m_validator = rhs.m_validator;
593   m_validator_baton = rhs.m_validator_baton;
594 }
595 
596 void StringExtractorGDBRemote::SetResponseValidator(
597     ResponseValidatorCallback callback, void *baton) {
598   m_validator = callback;
599   m_validator_baton = baton;
600 }
601 
602 void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() {
603   m_validator = OKErrorNotSupportedResponseValidator;
604   m_validator_baton = nullptr;
605 }
606 
607 void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() {
608   m_validator = ASCIIHexBytesResponseValidator;
609   m_validator_baton = nullptr;
610 }
611 
612 void StringExtractorGDBRemote::SetResponseValidatorToJSON() {
613   m_validator = JSONResponseValidator;
614   m_validator_baton = nullptr;
615 }
616 
617 bool StringExtractorGDBRemote::ValidateResponse() const {
618   // If we have a validator callback, try to validate the callback
619   if (m_validator)
620     return m_validator(m_validator_baton, *this);
621   else
622     return true; // No validator, so response is valid
623 }
624 
625 llvm::Optional<std::pair<lldb::pid_t, lldb::tid_t>>
626 StringExtractorGDBRemote::GetPidTid(lldb::pid_t default_pid) {
627   llvm::StringRef view = llvm::StringRef(m_packet).substr(m_index);
628   size_t initial_length = view.size();
629   lldb::pid_t pid = default_pid;
630   lldb::tid_t tid;
631 
632   if (view.consume_front("p")) {
633     // process identifier
634     if (view.consume_front("-1")) {
635       // -1 is a special case
636       pid = AllProcesses;
637     } else if (view.consumeInteger(16, pid) || pid == 0) {
638       // not a valid hex integer OR unsupported pid 0
639       m_index = UINT64_MAX;
640       return llvm::None;
641     }
642 
643     // "." must follow if we expect TID too; otherwise, we assume -1
644     if (!view.consume_front(".")) {
645       // update m_index
646       m_index += initial_length - view.size();
647 
648       return {{pid, AllThreads}};
649     }
650   }
651 
652   // thread identifier
653   if (view.consume_front("-1")) {
654     // -1 is a special case
655     tid = AllThreads;
656   } else if (view.consumeInteger(16, tid) || tid == 0 || pid == AllProcesses) {
657     // not a valid hex integer OR tid 0 OR pid -1 + a specific tid
658     m_index = UINT64_MAX;
659     return llvm::None;
660   }
661 
662   // update m_index
663   m_index += initial_length - view.size();
664 
665   return {{pid, tid}};
666 }
667