xref: /src/contrib/llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1cfca06d7SDimitry Andric //===-- StringExtractorGDBRemote.cpp --------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f73363f1SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
10f034231aSEd Maste 
11344a3780SDimitry Andric #include <cctype>
12344a3780SDimitry Andric #include <cstring>
13e3b55780SDimitry Andric #include <optional>
14344a3780SDimitry Andric 
15344a3780SDimitry Andric constexpr lldb::pid_t StringExtractorGDBRemote::AllProcesses;
16344a3780SDimitry Andric constexpr lldb::tid_t StringExtractorGDBRemote::AllThreads;
1774a628f7SDimitry Andric 
18f034231aSEd Maste StringExtractorGDBRemote::ResponseType
GetResponseType() const1914f1b3e8SDimitry Andric StringExtractorGDBRemote::GetResponseType() const {
20f034231aSEd Maste   if (m_packet.empty())
21f034231aSEd Maste     return eUnsupported;
22f034231aSEd Maste 
2314f1b3e8SDimitry Andric   switch (m_packet[0]) {
24f034231aSEd Maste   case 'E':
25e75e363cSDimitry Andric     if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) {
26e75e363cSDimitry Andric       if (m_packet.size() == 3)
27f034231aSEd Maste         return eError;
28e75e363cSDimitry Andric       llvm::StringRef packet_ref(m_packet);
29e75e363cSDimitry Andric       if (packet_ref[3] == ';') {
30e75e363cSDimitry Andric         auto err_string = packet_ref.substr(4);
31e75e363cSDimitry Andric         for (auto e : err_string)
32e75e363cSDimitry Andric           if (!isxdigit(e))
33e75e363cSDimitry Andric             return eResponse;
34e75e363cSDimitry Andric         return eError;
35e75e363cSDimitry Andric       }
36e75e363cSDimitry Andric     }
37f034231aSEd Maste     break;
38f034231aSEd Maste 
39f034231aSEd Maste   case 'O':
40f034231aSEd Maste     if (m_packet.size() == 2 && m_packet[1] == 'K')
41f034231aSEd Maste       return eOK;
42f034231aSEd Maste     break;
43f034231aSEd Maste 
44f034231aSEd Maste   case '+':
45f034231aSEd Maste     if (m_packet.size() == 1)
46f034231aSEd Maste       return eAck;
47f034231aSEd Maste     break;
48f034231aSEd Maste 
49f034231aSEd Maste   case '-':
50f034231aSEd Maste     if (m_packet.size() == 1)
51f034231aSEd Maste       return eNack;
52f034231aSEd Maste     break;
53f034231aSEd Maste   }
54f034231aSEd Maste   return eResponse;
55f034231aSEd Maste }
56f034231aSEd Maste 
57f034231aSEd Maste StringExtractorGDBRemote::ServerPacketType
GetServerPacketType() const5814f1b3e8SDimitry Andric StringExtractorGDBRemote::GetServerPacketType() const {
5914f1b3e8SDimitry Andric #define PACKET_MATCHES(s)                                                      \
6014f1b3e8SDimitry Andric   ((packet_size == (sizeof(s) - 1)) && (strcmp((packet_cstr), (s)) == 0))
6114f1b3e8SDimitry Andric #define PACKET_STARTS_WITH(s)                                                  \
6214f1b3e8SDimitry Andric   ((packet_size >= (sizeof(s) - 1)) &&                                         \
6314f1b3e8SDimitry Andric    ::strncmp(packet_cstr, s, (sizeof(s) - 1)) == 0)
64f034231aSEd Maste 
65f034231aSEd Maste   // Empty is not a supported packet...
66f034231aSEd Maste   if (m_packet.empty())
67f034231aSEd Maste     return eServerPacketType_invalid;
68f034231aSEd Maste 
69f034231aSEd Maste   const size_t packet_size = m_packet.size();
70f034231aSEd Maste   const char *packet_cstr = m_packet.c_str();
7114f1b3e8SDimitry Andric   switch (m_packet[0]) {
725e95aa85SEd Maste 
735e95aa85SEd Maste   case '%':
745e95aa85SEd Maste     return eServerPacketType_notify;
755e95aa85SEd Maste 
76f034231aSEd Maste   case '\x03':
7714f1b3e8SDimitry Andric     if (packet_size == 1)
7814f1b3e8SDimitry Andric       return eServerPacketType_interrupt;
79f034231aSEd Maste     break;
80f034231aSEd Maste 
81f034231aSEd Maste   case '-':
8214f1b3e8SDimitry Andric     if (packet_size == 1)
8314f1b3e8SDimitry Andric       return eServerPacketType_nack;
84f034231aSEd Maste     break;
85f034231aSEd Maste 
86f034231aSEd Maste   case '+':
8714f1b3e8SDimitry Andric     if (packet_size == 1)
8814f1b3e8SDimitry Andric       return eServerPacketType_ack;
89f034231aSEd Maste     break;
90f034231aSEd Maste 
91f034231aSEd Maste   case 'A':
92f034231aSEd Maste     return eServerPacketType_A;
93f034231aSEd Maste 
94f034231aSEd Maste   case 'Q':
95866dcdacSEd Maste 
9614f1b3e8SDimitry Andric     switch (packet_cstr[1]) {
97f034231aSEd Maste     case 'E':
9814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QEnvironment:"))
9914f1b3e8SDimitry Andric         return eServerPacketType_QEnvironment;
10014f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
10114f1b3e8SDimitry Andric         return eServerPacketType_QEnvironmentHexEncoded;
102e75e363cSDimitry Andric       if (PACKET_STARTS_WITH("QEnableErrorStrings"))
103e75e363cSDimitry Andric         return eServerPacketType_QEnableErrorStrings;
104f034231aSEd Maste       break;
105f034231aSEd Maste 
10674a628f7SDimitry Andric     case 'P':
10774a628f7SDimitry Andric       if (PACKET_STARTS_WITH("QPassSignals:"))
10874a628f7SDimitry Andric         return eServerPacketType_QPassSignals;
109ef5d0b5eSDimitry Andric       break;
11074a628f7SDimitry Andric 
111f034231aSEd Maste     case 'S':
11214f1b3e8SDimitry Andric       if (PACKET_MATCHES("QStartNoAckMode"))
11314f1b3e8SDimitry Andric         return eServerPacketType_QStartNoAckMode;
11414f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSaveRegisterState"))
11514f1b3e8SDimitry Andric         return eServerPacketType_QSaveRegisterState;
11614f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetDisableASLR:"))
11714f1b3e8SDimitry Andric         return eServerPacketType_QSetDisableASLR;
11814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetDetachOnError:"))
11914f1b3e8SDimitry Andric         return eServerPacketType_QSetDetachOnError;
12014f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetSTDIN:"))
12114f1b3e8SDimitry Andric         return eServerPacketType_QSetSTDIN;
12214f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetSTDOUT:"))
12314f1b3e8SDimitry Andric         return eServerPacketType_QSetSTDOUT;
12414f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetSTDERR:"))
12514f1b3e8SDimitry Andric         return eServerPacketType_QSetSTDERR;
12614f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetWorkingDir:"))
12714f1b3e8SDimitry Andric         return eServerPacketType_QSetWorkingDir;
12814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetLogging:"))
12914f1b3e8SDimitry Andric         return eServerPacketType_QSetLogging;
130145449b1SDimitry Andric       if (PACKET_STARTS_WITH("QSetIgnoredExceptions"))
131145449b1SDimitry Andric         return eServerPacketType_QSetIgnoredExceptions;
13214f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetMaxPacketSize:"))
13314f1b3e8SDimitry Andric         return eServerPacketType_QSetMaxPacketSize;
13414f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetMaxPayloadSize:"))
13514f1b3e8SDimitry Andric         return eServerPacketType_QSetMaxPayloadSize;
13614f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSetEnableAsyncProfiling;"))
13714f1b3e8SDimitry Andric         return eServerPacketType_QSetEnableAsyncProfiling;
13814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QSyncThreadState:"))
13914f1b3e8SDimitry Andric         return eServerPacketType_QSyncThreadState;
140f034231aSEd Maste       break;
141866dcdacSEd Maste 
142f21a844fSEd Maste     case 'L':
14314f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QLaunchArch:"))
14414f1b3e8SDimitry Andric         return eServerPacketType_QLaunchArch;
14514f1b3e8SDimitry Andric       if (PACKET_MATCHES("QListThreadsInStopReply"))
14614f1b3e8SDimitry Andric         return eServerPacketType_QListThreadsInStopReply;
147866dcdacSEd Maste       break;
148866dcdacSEd Maste 
149344a3780SDimitry Andric     case 'M':
150344a3780SDimitry Andric       if (PACKET_STARTS_WITH("QMemTags"))
151344a3780SDimitry Andric         return eServerPacketType_QMemTags;
152344a3780SDimitry Andric       break;
153344a3780SDimitry Andric 
154145449b1SDimitry Andric     case 'N':
155145449b1SDimitry Andric       if (PACKET_STARTS_WITH("QNonStop:"))
156145449b1SDimitry Andric         return eServerPacketType_QNonStop;
157145449b1SDimitry Andric       break;
158145449b1SDimitry Andric 
159866dcdacSEd Maste     case 'R':
16014f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("QRestoreRegisterState:"))
16114f1b3e8SDimitry Andric         return eServerPacketType_QRestoreRegisterState;
162866dcdacSEd Maste       break;
163866dcdacSEd Maste 
164866dcdacSEd Maste     case 'T':
16514f1b3e8SDimitry Andric       if (PACKET_MATCHES("QThreadSuffixSupported"))
16614f1b3e8SDimitry Andric         return eServerPacketType_QThreadSuffixSupported;
167f21a844fSEd Maste       break;
168f034231aSEd Maste     }
169f034231aSEd Maste     break;
170f034231aSEd Maste 
171f034231aSEd Maste   case 'q':
17214f1b3e8SDimitry Andric     switch (packet_cstr[1]) {
173f034231aSEd Maste     case 's':
17414f1b3e8SDimitry Andric       if (PACKET_MATCHES("qsProcessInfo"))
17514f1b3e8SDimitry Andric         return eServerPacketType_qsProcessInfo;
17614f1b3e8SDimitry Andric       if (PACKET_MATCHES("qsThreadInfo"))
17714f1b3e8SDimitry Andric         return eServerPacketType_qsThreadInfo;
178f034231aSEd Maste       break;
179f034231aSEd Maste 
180f034231aSEd Maste     case 'f':
18114f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qfProcessInfo"))
18214f1b3e8SDimitry Andric         return eServerPacketType_qfProcessInfo;
18314f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qfThreadInfo"))
18414f1b3e8SDimitry Andric         return eServerPacketType_qfThreadInfo;
185f034231aSEd Maste       break;
186f034231aSEd Maste 
187f034231aSEd Maste     case 'C':
18814f1b3e8SDimitry Andric       if (packet_size == 2)
18914f1b3e8SDimitry Andric         return eServerPacketType_qC;
190f034231aSEd Maste       break;
191f034231aSEd Maste 
1925e95aa85SEd Maste     case 'E':
19314f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qEcho:"))
19414f1b3e8SDimitry Andric         return eServerPacketType_qEcho;
1955e95aa85SEd Maste       break;
1965e95aa85SEd Maste 
1975e95aa85SEd Maste     case 'F':
19814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qFileLoadAddress:"))
19914f1b3e8SDimitry Andric         return eServerPacketType_qFileLoadAddress;
2005e95aa85SEd Maste       break;
2015e95aa85SEd Maste 
202f034231aSEd Maste     case 'G':
20314f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qGroupName:"))
20414f1b3e8SDimitry Andric         return eServerPacketType_qGroupName;
20514f1b3e8SDimitry Andric       if (PACKET_MATCHES("qGetWorkingDir"))
20614f1b3e8SDimitry Andric         return eServerPacketType_qGetWorkingDir;
20714f1b3e8SDimitry Andric       if (PACKET_MATCHES("qGetPid"))
20814f1b3e8SDimitry Andric         return eServerPacketType_qGetPid;
20914f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qGetProfileData;"))
21014f1b3e8SDimitry Andric         return eServerPacketType_qGetProfileData;
21114f1b3e8SDimitry Andric       if (PACKET_MATCHES("qGDBServerVersion"))
21214f1b3e8SDimitry Andric         return eServerPacketType_qGDBServerVersion;
213f034231aSEd Maste       break;
214f034231aSEd Maste 
215f034231aSEd Maste     case 'H':
21614f1b3e8SDimitry Andric       if (PACKET_MATCHES("qHostInfo"))
21714f1b3e8SDimitry Andric         return eServerPacketType_qHostInfo;
218f034231aSEd Maste       break;
219f034231aSEd Maste 
220f21a844fSEd Maste     case 'K':
22114f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qKillSpawnedProcess"))
22214f1b3e8SDimitry Andric         return eServerPacketType_qKillSpawnedProcess;
223f21a844fSEd Maste       break;
224f21a844fSEd Maste 
225f034231aSEd Maste     case 'L':
22614f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qLaunchGDBServer"))
22714f1b3e8SDimitry Andric         return eServerPacketType_qLaunchGDBServer;
22814f1b3e8SDimitry Andric       if (PACKET_MATCHES("qLaunchSuccess"))
22914f1b3e8SDimitry Andric         return eServerPacketType_qLaunchSuccess;
230f034231aSEd Maste       break;
231f034231aSEd Maste 
232866dcdacSEd Maste     case 'M':
23314f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qMemoryRegionInfo:"))
23414f1b3e8SDimitry Andric         return eServerPacketType_qMemoryRegionInfo;
23514f1b3e8SDimitry Andric       if (PACKET_MATCHES("qMemoryRegionInfo"))
23614f1b3e8SDimitry Andric         return eServerPacketType_qMemoryRegionInfoSupported;
23714f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qModuleInfo:"))
23814f1b3e8SDimitry Andric         return eServerPacketType_qModuleInfo;
239344a3780SDimitry Andric       if (PACKET_STARTS_WITH("qMemTags:"))
240344a3780SDimitry Andric         return eServerPacketType_qMemTags;
241866dcdacSEd Maste       break;
242866dcdacSEd Maste 
243f034231aSEd Maste     case 'P':
24414f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qProcessInfoPID:"))
24514f1b3e8SDimitry Andric         return eServerPacketType_qProcessInfoPID;
24614f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qPlatform_shell:"))
24714f1b3e8SDimitry Andric         return eServerPacketType_qPlatform_shell;
24814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qPlatform_mkdir:"))
24914f1b3e8SDimitry Andric         return eServerPacketType_qPlatform_mkdir;
25014f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qPlatform_chmod:"))
25114f1b3e8SDimitry Andric         return eServerPacketType_qPlatform_chmod;
25214f1b3e8SDimitry Andric       if (PACKET_MATCHES("qProcessInfo"))
25314f1b3e8SDimitry Andric         return eServerPacketType_qProcessInfo;
254b60736ecSDimitry Andric       if (PACKET_STARTS_WITH("qPathComplete:"))
255b60736ecSDimitry Andric         return eServerPacketType_qPathComplete;
256f034231aSEd Maste       break;
257f034231aSEd Maste 
258e81d9d49SDimitry Andric     case 'Q':
25914f1b3e8SDimitry Andric       if (PACKET_MATCHES("qQueryGDBServer"))
26014f1b3e8SDimitry Andric         return eServerPacketType_qQueryGDBServer;
261e81d9d49SDimitry Andric       break;
262e81d9d49SDimitry Andric 
263866dcdacSEd Maste     case 'R':
26414f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qRcmd,"))
26514f1b3e8SDimitry Andric         return eServerPacketType_qRcmd;
26614f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qRegisterInfo"))
26714f1b3e8SDimitry Andric         return eServerPacketType_qRegisterInfo;
268866dcdacSEd Maste       break;
269f21a844fSEd Maste 
270f034231aSEd Maste     case 'S':
271c0981da4SDimitry Andric       if (PACKET_STARTS_WITH("qSaveCore"))
272c0981da4SDimitry Andric         return eServerPacketType_qLLDBSaveCore;
27314f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qSpeedTest:"))
27414f1b3e8SDimitry Andric         return eServerPacketType_qSpeedTest;
27514f1b3e8SDimitry Andric       if (PACKET_MATCHES("qShlibInfoAddr"))
27614f1b3e8SDimitry Andric         return eServerPacketType_qShlibInfoAddr;
27714f1b3e8SDimitry Andric       if (PACKET_MATCHES("qStepPacketSupported"))
27814f1b3e8SDimitry Andric         return eServerPacketType_qStepPacketSupported;
27914f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qSupported"))
28014f1b3e8SDimitry Andric         return eServerPacketType_qSupported;
28114f1b3e8SDimitry Andric       if (PACKET_MATCHES("qSyncThreadStateSupported"))
28214f1b3e8SDimitry Andric         return eServerPacketType_qSyncThreadStateSupported;
283866dcdacSEd Maste       break;
284866dcdacSEd Maste 
285866dcdacSEd Maste     case 'T':
28614f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qThreadExtraInfo,"))
28714f1b3e8SDimitry Andric         return eServerPacketType_qThreadExtraInfo;
28814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qThreadStopInfo"))
28914f1b3e8SDimitry Andric         return eServerPacketType_qThreadStopInfo;
290f034231aSEd Maste       break;
291f034231aSEd Maste 
292f034231aSEd Maste     case 'U':
29314f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qUserName:"))
29414f1b3e8SDimitry Andric         return eServerPacketType_qUserName;
295f034231aSEd Maste       break;
296866dcdacSEd Maste 
297866dcdacSEd Maste     case 'V':
29814f1b3e8SDimitry Andric       if (PACKET_MATCHES("qVAttachOrWaitSupported"))
29914f1b3e8SDimitry Andric         return eServerPacketType_qVAttachOrWaitSupported;
300866dcdacSEd Maste       break;
301866dcdacSEd Maste 
302866dcdacSEd Maste     case 'W':
30314f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("qWatchpointSupportInfo:"))
30414f1b3e8SDimitry Andric         return eServerPacketType_qWatchpointSupportInfo;
30514f1b3e8SDimitry Andric       if (PACKET_MATCHES("qWatchpointSupportInfo"))
30614f1b3e8SDimitry Andric         return eServerPacketType_qWatchpointSupportInfoSupported;
307866dcdacSEd Maste       break;
3080cac4ca3SEd Maste 
3090cac4ca3SEd Maste     case 'X':
3105f29bb8aSDimitry Andric       if (PACKET_STARTS_WITH("qXfer:"))
3115f29bb8aSDimitry Andric         return eServerPacketType_qXfer;
3120cac4ca3SEd Maste       break;
313f034231aSEd Maste     }
314f034231aSEd Maste     break;
315027f1c96SDimitry Andric 
316027f1c96SDimitry Andric   case 'j':
31714f1b3e8SDimitry Andric     if (PACKET_STARTS_WITH("jModulesInfo:"))
31814f1b3e8SDimitry Andric       return eServerPacketType_jModulesInfo;
31914f1b3e8SDimitry Andric     if (PACKET_MATCHES("jSignalsInfo"))
32014f1b3e8SDimitry Andric       return eServerPacketType_jSignalsInfo;
32114f1b3e8SDimitry Andric     if (PACKET_MATCHES("jThreadsInfo"))
32214f1b3e8SDimitry Andric       return eServerPacketType_jThreadsInfo;
323344a3780SDimitry Andric 
324344a3780SDimitry Andric     if (PACKET_MATCHES("jLLDBTraceSupported"))
325344a3780SDimitry Andric       return eServerPacketType_jLLDBTraceSupported;
326344a3780SDimitry Andric     if (PACKET_STARTS_WITH("jLLDBTraceStop:"))
327344a3780SDimitry Andric       return eServerPacketType_jLLDBTraceStop;
328344a3780SDimitry Andric     if (PACKET_STARTS_WITH("jLLDBTraceStart:"))
329344a3780SDimitry Andric       return eServerPacketType_jLLDBTraceStart;
330344a3780SDimitry Andric     if (PACKET_STARTS_WITH("jLLDBTraceGetState:"))
331344a3780SDimitry Andric       return eServerPacketType_jLLDBTraceGetState;
332344a3780SDimitry Andric     if (PACKET_STARTS_WITH("jLLDBTraceGetBinaryData:"))
333344a3780SDimitry Andric       return eServerPacketType_jLLDBTraceGetBinaryData;
334f3fbd1c0SDimitry Andric     break;
335027f1c96SDimitry Andric 
336f21a844fSEd Maste   case 'v':
33714f1b3e8SDimitry Andric     if (PACKET_STARTS_WITH("vFile:")) {
33814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("vFile:open:"))
33914f1b3e8SDimitry Andric         return eServerPacketType_vFile_open;
34014f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:close:"))
34114f1b3e8SDimitry Andric         return eServerPacketType_vFile_close;
34214f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:pread"))
34314f1b3e8SDimitry Andric         return eServerPacketType_vFile_pread;
34414f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:pwrite"))
34514f1b3e8SDimitry Andric         return eServerPacketType_vFile_pwrite;
34614f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:size"))
34714f1b3e8SDimitry Andric         return eServerPacketType_vFile_size;
34814f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:exists"))
34914f1b3e8SDimitry Andric         return eServerPacketType_vFile_exists;
350c0981da4SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:fstat"))
351c0981da4SDimitry Andric         return eServerPacketType_vFile_fstat;
35214f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:stat"))
35314f1b3e8SDimitry Andric         return eServerPacketType_vFile_stat;
35414f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:mode"))
35514f1b3e8SDimitry Andric         return eServerPacketType_vFile_mode;
35614f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:MD5"))
35714f1b3e8SDimitry Andric         return eServerPacketType_vFile_md5;
35814f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:symlink"))
35914f1b3e8SDimitry Andric         return eServerPacketType_vFile_symlink;
36014f1b3e8SDimitry Andric       else if (PACKET_STARTS_WITH("vFile:unlink"))
36114f1b3e8SDimitry Andric         return eServerPacketType_vFile_unlink;
362f21a844fSEd Maste 
363866dcdacSEd Maste     } else {
36414f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("vAttach;"))
36514f1b3e8SDimitry Andric         return eServerPacketType_vAttach;
36614f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("vAttachWait;"))
36714f1b3e8SDimitry Andric         return eServerPacketType_vAttachWait;
36814f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("vAttachOrWait;"))
36914f1b3e8SDimitry Andric         return eServerPacketType_vAttachOrWait;
37014f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("vAttachName;"))
37114f1b3e8SDimitry Andric         return eServerPacketType_vAttachName;
37214f1b3e8SDimitry Andric       if (PACKET_STARTS_WITH("vCont;"))
37314f1b3e8SDimitry Andric         return eServerPacketType_vCont;
37414f1b3e8SDimitry Andric       if (PACKET_MATCHES("vCont?"))
37514f1b3e8SDimitry Andric         return eServerPacketType_vCont_actions;
376145449b1SDimitry Andric       if (PACKET_STARTS_WITH("vKill;"))
377145449b1SDimitry Andric         return eServerPacketType_vKill;
378c0981da4SDimitry Andric       if (PACKET_STARTS_WITH("vRun;"))
379c0981da4SDimitry Andric         return eServerPacketType_vRun;
380145449b1SDimitry Andric       if (PACKET_MATCHES("vStopped"))
381145449b1SDimitry Andric         return eServerPacketType_vStopped;
382145449b1SDimitry Andric       if (PACKET_MATCHES("vCtrlC"))
383145449b1SDimitry Andric         return eServerPacketType_vCtrlC;
3844b4fe385SDimitry Andric       if (PACKET_MATCHES("vStdio"))
3854b4fe385SDimitry Andric         return eServerPacketType_vStdio;
386145449b1SDimitry Andric       break;
387145449b1SDimitry Andric 
388f21a844fSEd Maste     }
389f21a844fSEd Maste     break;
390866dcdacSEd Maste   case '_':
39114f1b3e8SDimitry Andric     switch (packet_cstr[1]) {
392866dcdacSEd Maste     case 'M':
393866dcdacSEd Maste       return eServerPacketType__M;
394866dcdacSEd Maste 
395866dcdacSEd Maste     case 'm':
396866dcdacSEd Maste       return eServerPacketType__m;
397866dcdacSEd Maste     }
398866dcdacSEd Maste     break;
399866dcdacSEd Maste 
400866dcdacSEd Maste   case '?':
40114f1b3e8SDimitry Andric     if (packet_size == 1)
40214f1b3e8SDimitry Andric       return eServerPacketType_stop_reason;
403866dcdacSEd Maste     break;
404866dcdacSEd Maste 
405866dcdacSEd Maste   case 'c':
406866dcdacSEd Maste     return eServerPacketType_c;
407866dcdacSEd Maste 
408866dcdacSEd Maste   case 'C':
409866dcdacSEd Maste     return eServerPacketType_C;
410866dcdacSEd Maste 
411866dcdacSEd Maste   case 'D':
41214f1b3e8SDimitry Andric     return eServerPacketType_D;
413866dcdacSEd Maste 
414866dcdacSEd Maste   case 'g':
41514f1b3e8SDimitry Andric     return eServerPacketType_g;
416866dcdacSEd Maste 
417866dcdacSEd Maste   case 'G':
418866dcdacSEd Maste     return eServerPacketType_G;
419866dcdacSEd Maste 
420866dcdacSEd Maste   case 'H':
421866dcdacSEd Maste     return eServerPacketType_H;
422866dcdacSEd Maste 
42312bd4897SEd Maste   case 'I':
42412bd4897SEd Maste     return eServerPacketType_I;
42512bd4897SEd Maste 
426866dcdacSEd Maste   case 'k':
42714f1b3e8SDimitry Andric     if (packet_size == 1)
42814f1b3e8SDimitry Andric       return eServerPacketType_k;
429866dcdacSEd Maste     break;
430866dcdacSEd Maste 
431866dcdacSEd Maste   case 'm':
432866dcdacSEd Maste     return eServerPacketType_m;
433866dcdacSEd Maste 
434866dcdacSEd Maste   case 'M':
435866dcdacSEd Maste     return eServerPacketType_M;
436866dcdacSEd Maste 
437866dcdacSEd Maste   case 'p':
438866dcdacSEd Maste     return eServerPacketType_p;
439866dcdacSEd Maste 
440866dcdacSEd Maste   case 'P':
441866dcdacSEd Maste     return eServerPacketType_P;
442866dcdacSEd Maste 
443866dcdacSEd Maste   case 's':
44414f1b3e8SDimitry Andric     if (packet_size == 1)
44514f1b3e8SDimitry Andric       return eServerPacketType_s;
446866dcdacSEd Maste     break;
447866dcdacSEd Maste 
448866dcdacSEd Maste   case 'S':
449866dcdacSEd Maste     return eServerPacketType_S;
450866dcdacSEd Maste 
451e81d9d49SDimitry Andric   case 'x':
452e81d9d49SDimitry Andric     return eServerPacketType_x;
453e81d9d49SDimitry Andric 
454e81d9d49SDimitry Andric   case 'X':
455e81d9d49SDimitry Andric     return eServerPacketType_X;
456e81d9d49SDimitry Andric 
457866dcdacSEd Maste   case 'T':
458866dcdacSEd Maste     return eServerPacketType_T;
459866dcdacSEd Maste 
460866dcdacSEd Maste   case 'z':
461866dcdacSEd Maste     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
462866dcdacSEd Maste       return eServerPacketType_z;
463866dcdacSEd Maste     break;
464866dcdacSEd Maste 
465866dcdacSEd Maste   case 'Z':
466866dcdacSEd Maste     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
467866dcdacSEd Maste       return eServerPacketType_Z;
468866dcdacSEd Maste     break;
469f034231aSEd Maste   }
470f034231aSEd Maste   return eServerPacketType_unimplemented;
471f034231aSEd Maste }
472f034231aSEd Maste 
IsOKResponse() const47314f1b3e8SDimitry Andric bool StringExtractorGDBRemote::IsOKResponse() const {
474f034231aSEd Maste   return GetResponseType() == eOK;
475f034231aSEd Maste }
476f034231aSEd Maste 
IsUnsupportedResponse() const47714f1b3e8SDimitry Andric bool StringExtractorGDBRemote::IsUnsupportedResponse() const {
478f034231aSEd Maste   return GetResponseType() == eUnsupported;
479f034231aSEd Maste }
480f034231aSEd Maste 
IsNormalResponse() const48114f1b3e8SDimitry Andric bool StringExtractorGDBRemote::IsNormalResponse() const {
482f034231aSEd Maste   return GetResponseType() == eResponse;
483f034231aSEd Maste }
484f034231aSEd Maste 
IsErrorResponse() const48514f1b3e8SDimitry Andric bool StringExtractorGDBRemote::IsErrorResponse() const {
486e75e363cSDimitry Andric   return GetResponseType() == eError && isxdigit(m_packet[1]) &&
487e75e363cSDimitry Andric          isxdigit(m_packet[2]);
488f034231aSEd Maste }
489f034231aSEd Maste 
GetError()49014f1b3e8SDimitry Andric uint8_t StringExtractorGDBRemote::GetError() {
49114f1b3e8SDimitry Andric   if (GetResponseType() == eError) {
492f034231aSEd Maste     SetFilePos(1);
493f034231aSEd Maste     return GetHexU8(255);
494f034231aSEd Maste   }
495f034231aSEd Maste   return 0;
496f034231aSEd Maste }
497f21a844fSEd Maste 
GetStatus()498e75e363cSDimitry Andric lldb_private::Status StringExtractorGDBRemote::GetStatus() {
499e75e363cSDimitry Andric   lldb_private::Status error;
500e75e363cSDimitry Andric   if (GetResponseType() == eError) {
501e75e363cSDimitry Andric     SetFilePos(1);
502e75e363cSDimitry Andric     uint8_t errc = GetHexU8(255);
503e75e363cSDimitry Andric     error.SetError(errc, lldb::eErrorTypeGeneric);
504e75e363cSDimitry Andric 
505e75e363cSDimitry Andric     error.SetErrorStringWithFormat("Error %u", errc);
506e75e363cSDimitry Andric     std::string error_messg;
507e75e363cSDimitry Andric     if (GetChar() == ';') {
508e75e363cSDimitry Andric       GetHexByteString(error_messg);
509e75e363cSDimitry Andric       error.SetErrorString(error_messg);
510e75e363cSDimitry Andric     }
511e75e363cSDimitry Andric   }
512e75e363cSDimitry Andric   return error;
513e75e363cSDimitry Andric }
514e75e363cSDimitry Andric 
GetEscapedBinaryData(std::string & str)51514f1b3e8SDimitry Andric size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
51614f1b3e8SDimitry Andric   // Just get the data bytes in the string as
517f73363f1SDimitry Andric   // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
518f73363f1SDimitry Andric   // characters. If any 0x7d characters are left in the packet, then they are
519f73363f1SDimitry Andric   // supposed to be there...
520f21a844fSEd Maste   str.clear();
521205afe67SEd Maste   const size_t bytes_left = GetBytesLeft();
52214f1b3e8SDimitry Andric   if (bytes_left > 0) {
523205afe67SEd Maste     str.assign(m_packet, m_index, bytes_left);
524205afe67SEd Maste     m_index += bytes_left;
525f21a844fSEd Maste   }
526f21a844fSEd Maste   return str.size();
527f21a844fSEd Maste }
528f21a844fSEd Maste 
529f3fbd1c0SDimitry Andric static bool
OKErrorNotSupportedResponseValidator(void *,const StringExtractorGDBRemote & response)53014f1b3e8SDimitry Andric OKErrorNotSupportedResponseValidator(void *,
53114f1b3e8SDimitry Andric                                      const StringExtractorGDBRemote &response) {
53214f1b3e8SDimitry Andric   switch (response.GetResponseType()) {
533f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eOK:
534f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eError:
535f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eUnsupported:
536f3fbd1c0SDimitry Andric     return true;
537f3fbd1c0SDimitry Andric 
538f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eAck:
539f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eNack:
540f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eResponse:
541f3fbd1c0SDimitry Andric     break;
542f3fbd1c0SDimitry Andric   }
543f3fbd1c0SDimitry Andric   return false;
544f3fbd1c0SDimitry Andric }
545f3fbd1c0SDimitry Andric 
JSONResponseValidator(void *,const StringExtractorGDBRemote & response)54614f1b3e8SDimitry Andric static bool JSONResponseValidator(void *,
54714f1b3e8SDimitry Andric                                   const StringExtractorGDBRemote &response) {
54814f1b3e8SDimitry Andric   switch (response.GetResponseType()) {
549f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eUnsupported:
550f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eError:
551f3fbd1c0SDimitry Andric     return true; // Accept unsupported or EXX as valid responses
552f3fbd1c0SDimitry Andric 
553f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eOK:
554f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eAck:
555f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eNack:
556f3fbd1c0SDimitry Andric     break;
557f3fbd1c0SDimitry Andric 
558f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eResponse:
559f3fbd1c0SDimitry Andric     // JSON that is returned in from JSON query packets is currently always
560f73363f1SDimitry Andric     // either a dictionary which starts with a '{', or an array which starts
561f73363f1SDimitry Andric     // with a '['. This is a quick validator to just make sure the response
562f73363f1SDimitry Andric     // could be valid JSON without having to validate all of the
563f3fbd1c0SDimitry Andric     // JSON content.
56414f1b3e8SDimitry Andric     switch (response.GetStringRef()[0]) {
56514f1b3e8SDimitry Andric     case '{':
56614f1b3e8SDimitry Andric       return true;
56714f1b3e8SDimitry Andric     case '[':
56814f1b3e8SDimitry Andric       return true;
569f3fbd1c0SDimitry Andric     default:
570f3fbd1c0SDimitry Andric       break;
571f3fbd1c0SDimitry Andric     }
572f3fbd1c0SDimitry Andric     break;
573f3fbd1c0SDimitry Andric   }
574f3fbd1c0SDimitry Andric   return false;
575f3fbd1c0SDimitry Andric }
576f3fbd1c0SDimitry Andric 
577f3fbd1c0SDimitry Andric static bool
ASCIIHexBytesResponseValidator(void *,const StringExtractorGDBRemote & response)57814f1b3e8SDimitry Andric ASCIIHexBytesResponseValidator(void *,
57914f1b3e8SDimitry Andric                                const StringExtractorGDBRemote &response) {
58014f1b3e8SDimitry Andric   switch (response.GetResponseType()) {
581f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eUnsupported:
582f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eError:
583f3fbd1c0SDimitry Andric     return true; // Accept unsupported or EXX as valid responses
584f3fbd1c0SDimitry Andric 
585f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eOK:
586f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eAck:
587f3fbd1c0SDimitry Andric   case StringExtractorGDBRemote::eNack:
588f3fbd1c0SDimitry Andric     break;
589f3fbd1c0SDimitry Andric 
59014f1b3e8SDimitry Andric   case StringExtractorGDBRemote::eResponse: {
591f3fbd1c0SDimitry Andric     uint32_t valid_count = 0;
59214f1b3e8SDimitry Andric     for (const char ch : response.GetStringRef()) {
59314f1b3e8SDimitry Andric       if (!isxdigit(ch)) {
594f3fbd1c0SDimitry Andric         return false;
595f3fbd1c0SDimitry Andric       }
596f3fbd1c0SDimitry Andric       if (++valid_count >= 16)
59714f1b3e8SDimitry Andric         break; // Don't validate all the characters in case the packet is very
59814f1b3e8SDimitry Andric                // large
599f3fbd1c0SDimitry Andric     }
600f3fbd1c0SDimitry Andric     return true;
60114f1b3e8SDimitry Andric   } break;
602f3fbd1c0SDimitry Andric   }
603f3fbd1c0SDimitry Andric   return false;
604f3fbd1c0SDimitry Andric }
605f3fbd1c0SDimitry Andric 
CopyResponseValidator(const StringExtractorGDBRemote & rhs)60614f1b3e8SDimitry Andric void StringExtractorGDBRemote::CopyResponseValidator(
60714f1b3e8SDimitry Andric     const StringExtractorGDBRemote &rhs) {
608f3fbd1c0SDimitry Andric   m_validator = rhs.m_validator;
609f3fbd1c0SDimitry Andric   m_validator_baton = rhs.m_validator_baton;
610f3fbd1c0SDimitry Andric }
611f3fbd1c0SDimitry Andric 
SetResponseValidator(ResponseValidatorCallback callback,void * baton)61214f1b3e8SDimitry Andric void StringExtractorGDBRemote::SetResponseValidator(
61314f1b3e8SDimitry Andric     ResponseValidatorCallback callback, void *baton) {
614f3fbd1c0SDimitry Andric   m_validator = callback;
615f3fbd1c0SDimitry Andric   m_validator_baton = baton;
616f3fbd1c0SDimitry Andric }
617f3fbd1c0SDimitry Andric 
SetResponseValidatorToOKErrorNotSupported()61814f1b3e8SDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() {
619f3fbd1c0SDimitry Andric   m_validator = OKErrorNotSupportedResponseValidator;
620f3fbd1c0SDimitry Andric   m_validator_baton = nullptr;
621f3fbd1c0SDimitry Andric }
622f3fbd1c0SDimitry Andric 
SetResponseValidatorToASCIIHexBytes()62314f1b3e8SDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() {
624f3fbd1c0SDimitry Andric   m_validator = ASCIIHexBytesResponseValidator;
625f3fbd1c0SDimitry Andric   m_validator_baton = nullptr;
626f3fbd1c0SDimitry Andric }
627f3fbd1c0SDimitry Andric 
SetResponseValidatorToJSON()62814f1b3e8SDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToJSON() {
629f3fbd1c0SDimitry Andric   m_validator = JSONResponseValidator;
630f3fbd1c0SDimitry Andric   m_validator_baton = nullptr;
631f3fbd1c0SDimitry Andric }
632f3fbd1c0SDimitry Andric 
ValidateResponse() const63314f1b3e8SDimitry Andric bool StringExtractorGDBRemote::ValidateResponse() const {
634f3fbd1c0SDimitry Andric   // If we have a validator callback, try to validate the callback
635f3fbd1c0SDimitry Andric   if (m_validator)
636f3fbd1c0SDimitry Andric     return m_validator(m_validator_baton, *this);
637f3fbd1c0SDimitry Andric   else
638f3fbd1c0SDimitry Andric     return true; // No validator, so response is valid
639f3fbd1c0SDimitry Andric }
640344a3780SDimitry Andric 
641e3b55780SDimitry Andric std::optional<std::pair<lldb::pid_t, lldb::tid_t>>
GetPidTid(lldb::pid_t default_pid)642344a3780SDimitry Andric StringExtractorGDBRemote::GetPidTid(lldb::pid_t default_pid) {
643344a3780SDimitry Andric   llvm::StringRef view = llvm::StringRef(m_packet).substr(m_index);
644344a3780SDimitry Andric   size_t initial_length = view.size();
645145449b1SDimitry Andric   lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
646344a3780SDimitry Andric   lldb::tid_t tid;
647344a3780SDimitry Andric 
648344a3780SDimitry Andric   if (view.consume_front("p")) {
649344a3780SDimitry Andric     // process identifier
650344a3780SDimitry Andric     if (view.consume_front("-1")) {
651344a3780SDimitry Andric       // -1 is a special case
652344a3780SDimitry Andric       pid = AllProcesses;
653344a3780SDimitry Andric     } else if (view.consumeInteger(16, pid) || pid == 0) {
654344a3780SDimitry Andric       // not a valid hex integer OR unsupported pid 0
655344a3780SDimitry Andric       m_index = UINT64_MAX;
656e3b55780SDimitry Andric       return std::nullopt;
657344a3780SDimitry Andric     }
658344a3780SDimitry Andric 
659344a3780SDimitry Andric     // "." must follow if we expect TID too; otherwise, we assume -1
660344a3780SDimitry Andric     if (!view.consume_front(".")) {
661344a3780SDimitry Andric       // update m_index
662344a3780SDimitry Andric       m_index += initial_length - view.size();
663344a3780SDimitry Andric 
664344a3780SDimitry Andric       return {{pid, AllThreads}};
665344a3780SDimitry Andric     }
666344a3780SDimitry Andric   }
667344a3780SDimitry Andric 
668344a3780SDimitry Andric   // thread identifier
669344a3780SDimitry Andric   if (view.consume_front("-1")) {
670344a3780SDimitry Andric     // -1 is a special case
671344a3780SDimitry Andric     tid = AllThreads;
672344a3780SDimitry Andric   } else if (view.consumeInteger(16, tid) || tid == 0 || pid == AllProcesses) {
673344a3780SDimitry Andric     // not a valid hex integer OR tid 0 OR pid -1 + a specific tid
674344a3780SDimitry Andric     m_index = UINT64_MAX;
675e3b55780SDimitry Andric     return std::nullopt;
676344a3780SDimitry Andric   }
677344a3780SDimitry Andric 
678344a3780SDimitry Andric   // update m_index
679344a3780SDimitry Andric   m_index += initial_length - view.size();
680344a3780SDimitry Andric 
681145449b1SDimitry Andric   return {{pid != LLDB_INVALID_PROCESS_ID ? pid : default_pid, tid}};
682344a3780SDimitry Andric }
683