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