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