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