]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Utility / StringExtractorGDBRemote.cpp
1 //===-- StringExtractorGDBRemote.cpp ----------------------------*- C++ -*-===//
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
15 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
54 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       break;
237
238     case 'Q':
239       if (PACKET_MATCHES("qQueryGDBServer"))
240         return eServerPacketType_qQueryGDBServer;
241       break;
242
243     case 'R':
244       if (PACKET_STARTS_WITH("qRcmd,"))
245         return eServerPacketType_qRcmd;
246       if (PACKET_STARTS_WITH("qRegisterInfo"))
247         return eServerPacketType_qRegisterInfo;
248       break;
249
250     case 'S':
251       if (PACKET_STARTS_WITH("qSpeedTest:"))
252         return eServerPacketType_qSpeedTest;
253       if (PACKET_MATCHES("qShlibInfoAddr"))
254         return eServerPacketType_qShlibInfoAddr;
255       if (PACKET_MATCHES("qStepPacketSupported"))
256         return eServerPacketType_qStepPacketSupported;
257       if (PACKET_STARTS_WITH("qSupported"))
258         return eServerPacketType_qSupported;
259       if (PACKET_MATCHES("qSyncThreadStateSupported"))
260         return eServerPacketType_qSyncThreadStateSupported;
261       break;
262
263     case 'T':
264       if (PACKET_STARTS_WITH("qThreadExtraInfo,"))
265         return eServerPacketType_qThreadExtraInfo;
266       if (PACKET_STARTS_WITH("qThreadStopInfo"))
267         return eServerPacketType_qThreadStopInfo;
268       break;
269
270     case 'U':
271       if (PACKET_STARTS_WITH("qUserName:"))
272         return eServerPacketType_qUserName;
273       break;
274
275     case 'V':
276       if (PACKET_MATCHES("qVAttachOrWaitSupported"))
277         return eServerPacketType_qVAttachOrWaitSupported;
278       break;
279
280     case 'W':
281       if (PACKET_STARTS_WITH("qWatchpointSupportInfo:"))
282         return eServerPacketType_qWatchpointSupportInfo;
283       if (PACKET_MATCHES("qWatchpointSupportInfo"))
284         return eServerPacketType_qWatchpointSupportInfoSupported;
285       break;
286
287     case 'X':
288       if (PACKET_STARTS_WITH("qXfer:"))
289         return eServerPacketType_qXfer;
290       break;
291     }
292     break;
293
294   case 'j':
295     if (PACKET_STARTS_WITH("jModulesInfo:"))
296       return eServerPacketType_jModulesInfo;
297     if (PACKET_MATCHES("jSignalsInfo"))
298       return eServerPacketType_jSignalsInfo;
299     if (PACKET_MATCHES("jThreadsInfo"))
300       return eServerPacketType_jThreadsInfo;
301     if (PACKET_STARTS_WITH("jTraceBufferRead:"))
302       return eServerPacketType_jTraceBufferRead;
303     if (PACKET_STARTS_WITH("jTraceConfigRead:"))
304       return eServerPacketType_jTraceConfigRead;
305     if (PACKET_STARTS_WITH("jTraceMetaRead:"))
306       return eServerPacketType_jTraceMetaRead;
307     if (PACKET_STARTS_WITH("jTraceStart:"))
308       return eServerPacketType_jTraceStart;
309     if (PACKET_STARTS_WITH("jTraceStop:"))
310       return eServerPacketType_jTraceStop;
311     break;
312
313   case 'v':
314     if (PACKET_STARTS_WITH("vFile:")) {
315       if (PACKET_STARTS_WITH("vFile:open:"))
316         return eServerPacketType_vFile_open;
317       else if (PACKET_STARTS_WITH("vFile:close:"))
318         return eServerPacketType_vFile_close;
319       else if (PACKET_STARTS_WITH("vFile:pread"))
320         return eServerPacketType_vFile_pread;
321       else if (PACKET_STARTS_WITH("vFile:pwrite"))
322         return eServerPacketType_vFile_pwrite;
323       else if (PACKET_STARTS_WITH("vFile:size"))
324         return eServerPacketType_vFile_size;
325       else if (PACKET_STARTS_WITH("vFile:exists"))
326         return eServerPacketType_vFile_exists;
327       else if (PACKET_STARTS_WITH("vFile:stat"))
328         return eServerPacketType_vFile_stat;
329       else if (PACKET_STARTS_WITH("vFile:mode"))
330         return eServerPacketType_vFile_mode;
331       else if (PACKET_STARTS_WITH("vFile:MD5"))
332         return eServerPacketType_vFile_md5;
333       else if (PACKET_STARTS_WITH("vFile:symlink"))
334         return eServerPacketType_vFile_symlink;
335       else if (PACKET_STARTS_WITH("vFile:unlink"))
336         return eServerPacketType_vFile_unlink;
337
338     } else {
339       if (PACKET_STARTS_WITH("vAttach;"))
340         return eServerPacketType_vAttach;
341       if (PACKET_STARTS_WITH("vAttachWait;"))
342         return eServerPacketType_vAttachWait;
343       if (PACKET_STARTS_WITH("vAttachOrWait;"))
344         return eServerPacketType_vAttachOrWait;
345       if (PACKET_STARTS_WITH("vAttachName;"))
346         return eServerPacketType_vAttachName;
347       if (PACKET_STARTS_WITH("vCont;"))
348         return eServerPacketType_vCont;
349       if (PACKET_MATCHES("vCont?"))
350         return eServerPacketType_vCont_actions;
351     }
352     break;
353   case '_':
354     switch (packet_cstr[1]) {
355     case 'M':
356       return eServerPacketType__M;
357
358     case 'm':
359       return eServerPacketType__m;
360     }
361     break;
362
363   case '?':
364     if (packet_size == 1)
365       return eServerPacketType_stop_reason;
366     break;
367
368   case 'c':
369     return eServerPacketType_c;
370
371   case 'C':
372     return eServerPacketType_C;
373
374   case 'D':
375     if (packet_size == 1)
376       return eServerPacketType_D;
377     break;
378
379   case 'g':
380     return eServerPacketType_g;
381
382   case 'G':
383     return eServerPacketType_G;
384
385   case 'H':
386     return eServerPacketType_H;
387
388   case 'I':
389     return eServerPacketType_I;
390
391   case 'k':
392     if (packet_size == 1)
393       return eServerPacketType_k;
394     break;
395
396   case 'm':
397     return eServerPacketType_m;
398
399   case 'M':
400     return eServerPacketType_M;
401
402   case 'p':
403     return eServerPacketType_p;
404
405   case 'P':
406     return eServerPacketType_P;
407
408   case 's':
409     if (packet_size == 1)
410       return eServerPacketType_s;
411     break;
412
413   case 'S':
414     return eServerPacketType_S;
415
416   case 'x':
417     return eServerPacketType_x;
418
419   case 'X':
420     return eServerPacketType_X;
421
422   case 'T':
423     return eServerPacketType_T;
424
425   case 'z':
426     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
427       return eServerPacketType_z;
428     break;
429
430   case 'Z':
431     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
432       return eServerPacketType_Z;
433     break;
434   }
435   return eServerPacketType_unimplemented;
436 }
437
438 bool StringExtractorGDBRemote::IsOKResponse() const {
439   return GetResponseType() == eOK;
440 }
441
442 bool StringExtractorGDBRemote::IsUnsupportedResponse() const {
443   return GetResponseType() == eUnsupported;
444 }
445
446 bool StringExtractorGDBRemote::IsNormalResponse() const {
447   return GetResponseType() == eResponse;
448 }
449
450 bool StringExtractorGDBRemote::IsErrorResponse() const {
451   return GetResponseType() == eError && isxdigit(m_packet[1]) &&
452          isxdigit(m_packet[2]);
453 }
454
455 uint8_t StringExtractorGDBRemote::GetError() {
456   if (GetResponseType() == eError) {
457     SetFilePos(1);
458     return GetHexU8(255);
459   }
460   return 0;
461 }
462
463 lldb_private::Status StringExtractorGDBRemote::GetStatus() {
464   lldb_private::Status error;
465   if (GetResponseType() == eError) {
466     SetFilePos(1);
467     uint8_t errc = GetHexU8(255);
468     error.SetError(errc, lldb::eErrorTypeGeneric);
469
470     error.SetErrorStringWithFormat("Error %u", errc);
471     std::string error_messg;
472     if (GetChar() == ';') {
473       GetHexByteString(error_messg);
474       error.SetErrorString(error_messg);
475     }
476   }
477   return error;
478 }
479
480 size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
481   // Just get the data bytes in the string as
482   // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
483   // characters. If any 0x7d characters are left in the packet, then they are
484   // supposed to be there...
485   str.clear();
486   const size_t bytes_left = GetBytesLeft();
487   if (bytes_left > 0) {
488     str.assign(m_packet, m_index, bytes_left);
489     m_index += bytes_left;
490   }
491   return str.size();
492 }
493
494 static bool
495 OKErrorNotSupportedResponseValidator(void *,
496                                      const StringExtractorGDBRemote &response) {
497   switch (response.GetResponseType()) {
498   case StringExtractorGDBRemote::eOK:
499   case StringExtractorGDBRemote::eError:
500   case StringExtractorGDBRemote::eUnsupported:
501     return true;
502
503   case StringExtractorGDBRemote::eAck:
504   case StringExtractorGDBRemote::eNack:
505   case StringExtractorGDBRemote::eResponse:
506     break;
507   }
508   return false;
509 }
510
511 static bool JSONResponseValidator(void *,
512                                   const StringExtractorGDBRemote &response) {
513   switch (response.GetResponseType()) {
514   case StringExtractorGDBRemote::eUnsupported:
515   case StringExtractorGDBRemote::eError:
516     return true; // Accept unsupported or EXX as valid responses
517
518   case StringExtractorGDBRemote::eOK:
519   case StringExtractorGDBRemote::eAck:
520   case StringExtractorGDBRemote::eNack:
521     break;
522
523   case StringExtractorGDBRemote::eResponse:
524     // JSON that is returned in from JSON query packets is currently always
525     // either a dictionary which starts with a '{', or an array which starts
526     // with a '['. This is a quick validator to just make sure the response
527     // could be valid JSON without having to validate all of the
528     // JSON content.
529     switch (response.GetStringRef()[0]) {
530     case '{':
531       return true;
532     case '[':
533       return true;
534     default:
535       break;
536     }
537     break;
538   }
539   return false;
540 }
541
542 static bool
543 ASCIIHexBytesResponseValidator(void *,
544                                const StringExtractorGDBRemote &response) {
545   switch (response.GetResponseType()) {
546   case StringExtractorGDBRemote::eUnsupported:
547   case StringExtractorGDBRemote::eError:
548     return true; // Accept unsupported or EXX as valid responses
549
550   case StringExtractorGDBRemote::eOK:
551   case StringExtractorGDBRemote::eAck:
552   case StringExtractorGDBRemote::eNack:
553     break;
554
555   case StringExtractorGDBRemote::eResponse: {
556     uint32_t valid_count = 0;
557     for (const char ch : response.GetStringRef()) {
558       if (!isxdigit(ch)) {
559         return false;
560       }
561       if (++valid_count >= 16)
562         break; // Don't validate all the characters in case the packet is very
563                // large
564     }
565     return true;
566   } break;
567   }
568   return false;
569 }
570
571 void StringExtractorGDBRemote::CopyResponseValidator(
572     const StringExtractorGDBRemote &rhs) {
573   m_validator = rhs.m_validator;
574   m_validator_baton = rhs.m_validator_baton;
575 }
576
577 void StringExtractorGDBRemote::SetResponseValidator(
578     ResponseValidatorCallback callback, void *baton) {
579   m_validator = callback;
580   m_validator_baton = baton;
581 }
582
583 void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() {
584   m_validator = OKErrorNotSupportedResponseValidator;
585   m_validator_baton = nullptr;
586 }
587
588 void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() {
589   m_validator = ASCIIHexBytesResponseValidator;
590   m_validator_baton = nullptr;
591 }
592
593 void StringExtractorGDBRemote::SetResponseValidatorToJSON() {
594   m_validator = JSONResponseValidator;
595   m_validator_baton = nullptr;
596 }
597
598 bool StringExtractorGDBRemote::ValidateResponse() const {
599   // If we have a validator callback, try to validate the callback
600   if (m_validator)
601     return m_validator(m_validator_baton, *this);
602   else
603     return true; // No validator, so response is valid
604 }