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