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