1ac7ddfbfSEd Maste //===-- StringExtractorGDBRemote.cpp ----------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
104ba319b5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
11ac7ddfbfSEd Maste 
12*b5893f02SDimitry Andric #include <ctype.h>
13f678e45dSDimitry Andric #include <string.h>
14f678e45dSDimitry Andric 
15ac7ddfbfSEd Maste StringExtractorGDBRemote::ResponseType
GetResponseType() const16435933ddSDimitry Andric StringExtractorGDBRemote::GetResponseType() const {
17ac7ddfbfSEd Maste   if (m_packet.empty())
18ac7ddfbfSEd Maste     return eUnsupported;
19ac7ddfbfSEd Maste 
20435933ddSDimitry Andric   switch (m_packet[0]) {
21ac7ddfbfSEd Maste   case 'E':
22c4394386SDimitry Andric     if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) {
23c4394386SDimitry Andric       if (m_packet.size() == 3)
24ac7ddfbfSEd Maste         return eError;
25c4394386SDimitry Andric       llvm::StringRef packet_ref(m_packet);
26c4394386SDimitry Andric       if (packet_ref[3] == ';') {
27c4394386SDimitry Andric         auto err_string = packet_ref.substr(4);
28c4394386SDimitry Andric         for (auto e : err_string)
29c4394386SDimitry Andric           if (!isxdigit(e))
30c4394386SDimitry Andric             return eResponse;
31c4394386SDimitry Andric         return eError;
32c4394386SDimitry Andric       }
33c4394386SDimitry Andric     }
34ac7ddfbfSEd Maste     break;
35ac7ddfbfSEd Maste 
36ac7ddfbfSEd Maste   case 'O':
37ac7ddfbfSEd Maste     if (m_packet.size() == 2 && m_packet[1] == 'K')
38ac7ddfbfSEd Maste       return eOK;
39ac7ddfbfSEd Maste     break;
40ac7ddfbfSEd Maste 
41ac7ddfbfSEd Maste   case '+':
42ac7ddfbfSEd Maste     if (m_packet.size() == 1)
43ac7ddfbfSEd Maste       return eAck;
44ac7ddfbfSEd Maste     break;
45ac7ddfbfSEd Maste 
46ac7ddfbfSEd Maste   case '-':
47ac7ddfbfSEd Maste     if (m_packet.size() == 1)
48ac7ddfbfSEd Maste       return eNack;
49ac7ddfbfSEd Maste     break;
50ac7ddfbfSEd Maste   }
51ac7ddfbfSEd Maste   return eResponse;
52ac7ddfbfSEd Maste }
53ac7ddfbfSEd Maste 
54ac7ddfbfSEd Maste StringExtractorGDBRemote::ServerPacketType
GetServerPacketType() const55435933ddSDimitry Andric StringExtractorGDBRemote::GetServerPacketType() const {
56435933ddSDimitry Andric #define PACKET_MATCHES(s)                                                      \
57435933ddSDimitry Andric   ((packet_size == (sizeof(s) - 1)) && (strcmp((packet_cstr), (s)) == 0))
58435933ddSDimitry Andric #define PACKET_STARTS_WITH(s)                                                  \
59435933ddSDimitry Andric   ((packet_size >= (sizeof(s) - 1)) &&                                         \
60435933ddSDimitry Andric    ::strncmp(packet_cstr, s, (sizeof(s) - 1)) == 0)
61ac7ddfbfSEd Maste 
62ac7ddfbfSEd Maste   // Empty is not a supported packet...
63ac7ddfbfSEd Maste   if (m_packet.empty())
64ac7ddfbfSEd Maste     return eServerPacketType_invalid;
65ac7ddfbfSEd Maste 
66ac7ddfbfSEd Maste   const size_t packet_size = m_packet.size();
67ac7ddfbfSEd Maste   const char *packet_cstr = m_packet.c_str();
68435933ddSDimitry Andric   switch (m_packet[0]) {
691c3bbb01SEd Maste 
701c3bbb01SEd Maste   case '%':
711c3bbb01SEd Maste     return eServerPacketType_notify;
721c3bbb01SEd Maste 
73ac7ddfbfSEd Maste   case '\x03':
74435933ddSDimitry Andric     if (packet_size == 1)
75435933ddSDimitry Andric       return eServerPacketType_interrupt;
76ac7ddfbfSEd Maste     break;
77ac7ddfbfSEd Maste 
78ac7ddfbfSEd Maste   case '-':
79435933ddSDimitry Andric     if (packet_size == 1)
80435933ddSDimitry Andric       return eServerPacketType_nack;
81ac7ddfbfSEd Maste     break;
82ac7ddfbfSEd Maste 
83ac7ddfbfSEd Maste   case '+':
84435933ddSDimitry Andric     if (packet_size == 1)
85435933ddSDimitry Andric       return eServerPacketType_ack;
86ac7ddfbfSEd Maste     break;
87ac7ddfbfSEd Maste 
88ac7ddfbfSEd Maste   case 'A':
89ac7ddfbfSEd Maste     return eServerPacketType_A;
90ac7ddfbfSEd Maste 
91ac7ddfbfSEd Maste   case 'Q':
9212b93ac6SEd Maste 
93435933ddSDimitry Andric     switch (packet_cstr[1]) {
94ac7ddfbfSEd Maste     case 'E':
95435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QEnvironment:"))
96435933ddSDimitry Andric         return eServerPacketType_QEnvironment;
97435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:"))
98435933ddSDimitry Andric         return eServerPacketType_QEnvironmentHexEncoded;
99c4394386SDimitry Andric       if (PACKET_STARTS_WITH("QEnableErrorStrings"))
100c4394386SDimitry Andric         return eServerPacketType_QEnableErrorStrings;
101ac7ddfbfSEd Maste       break;
102ac7ddfbfSEd Maste 
103f678e45dSDimitry Andric     case 'P':
104f678e45dSDimitry Andric       if (PACKET_STARTS_WITH("QPassSignals:"))
105f678e45dSDimitry Andric         return eServerPacketType_QPassSignals;
106acac075bSDimitry Andric       break;
107f678e45dSDimitry Andric 
108ac7ddfbfSEd Maste     case 'S':
109435933ddSDimitry Andric       if (PACKET_MATCHES("QStartNoAckMode"))
110435933ddSDimitry Andric         return eServerPacketType_QStartNoAckMode;
111435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSaveRegisterState"))
112435933ddSDimitry Andric         return eServerPacketType_QSaveRegisterState;
113435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetDisableASLR:"))
114435933ddSDimitry Andric         return eServerPacketType_QSetDisableASLR;
115435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetDetachOnError:"))
116435933ddSDimitry Andric         return eServerPacketType_QSetDetachOnError;
117435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetSTDIN:"))
118435933ddSDimitry Andric         return eServerPacketType_QSetSTDIN;
119435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetSTDOUT:"))
120435933ddSDimitry Andric         return eServerPacketType_QSetSTDOUT;
121435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetSTDERR:"))
122435933ddSDimitry Andric         return eServerPacketType_QSetSTDERR;
123435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetWorkingDir:"))
124435933ddSDimitry Andric         return eServerPacketType_QSetWorkingDir;
125435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetLogging:"))
126435933ddSDimitry Andric         return eServerPacketType_QSetLogging;
127435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetMaxPacketSize:"))
128435933ddSDimitry Andric         return eServerPacketType_QSetMaxPacketSize;
129435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetMaxPayloadSize:"))
130435933ddSDimitry Andric         return eServerPacketType_QSetMaxPayloadSize;
131435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSetEnableAsyncProfiling;"))
132435933ddSDimitry Andric         return eServerPacketType_QSetEnableAsyncProfiling;
133435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QSyncThreadState:"))
134435933ddSDimitry Andric         return eServerPacketType_QSyncThreadState;
135ac7ddfbfSEd Maste       break;
13612b93ac6SEd Maste 
13735617911SEd Maste     case 'L':
138435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QLaunchArch:"))
139435933ddSDimitry Andric         return eServerPacketType_QLaunchArch;
140435933ddSDimitry Andric       if (PACKET_MATCHES("QListThreadsInStopReply"))
141435933ddSDimitry Andric         return eServerPacketType_QListThreadsInStopReply;
14212b93ac6SEd Maste       break;
14312b93ac6SEd Maste 
14412b93ac6SEd Maste     case 'R':
145435933ddSDimitry Andric       if (PACKET_STARTS_WITH("QRestoreRegisterState:"))
146435933ddSDimitry Andric         return eServerPacketType_QRestoreRegisterState;
14712b93ac6SEd Maste       break;
14812b93ac6SEd Maste 
14912b93ac6SEd Maste     case 'T':
150435933ddSDimitry Andric       if (PACKET_MATCHES("QThreadSuffixSupported"))
151435933ddSDimitry Andric         return eServerPacketType_QThreadSuffixSupported;
15235617911SEd Maste       break;
153ac7ddfbfSEd Maste     }
154ac7ddfbfSEd Maste     break;
155ac7ddfbfSEd Maste 
156ac7ddfbfSEd Maste   case 'q':
157435933ddSDimitry Andric     switch (packet_cstr[1]) {
158ac7ddfbfSEd Maste     case 's':
159435933ddSDimitry Andric       if (PACKET_MATCHES("qsProcessInfo"))
160435933ddSDimitry Andric         return eServerPacketType_qsProcessInfo;
161435933ddSDimitry Andric       if (PACKET_MATCHES("qsThreadInfo"))
162435933ddSDimitry Andric         return eServerPacketType_qsThreadInfo;
163ac7ddfbfSEd Maste       break;
164ac7ddfbfSEd Maste 
165ac7ddfbfSEd Maste     case 'f':
166435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qfProcessInfo"))
167435933ddSDimitry Andric         return eServerPacketType_qfProcessInfo;
168435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qfThreadInfo"))
169435933ddSDimitry Andric         return eServerPacketType_qfThreadInfo;
170ac7ddfbfSEd Maste       break;
171ac7ddfbfSEd Maste 
172ac7ddfbfSEd Maste     case 'C':
173435933ddSDimitry Andric       if (packet_size == 2)
174435933ddSDimitry Andric         return eServerPacketType_qC;
175ac7ddfbfSEd Maste       break;
176ac7ddfbfSEd Maste 
1771c3bbb01SEd Maste     case 'E':
178435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qEcho:"))
179435933ddSDimitry Andric         return eServerPacketType_qEcho;
1801c3bbb01SEd Maste       break;
1811c3bbb01SEd Maste 
1821c3bbb01SEd Maste     case 'F':
183435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qFileLoadAddress:"))
184435933ddSDimitry Andric         return eServerPacketType_qFileLoadAddress;
1851c3bbb01SEd Maste       break;
1861c3bbb01SEd Maste 
187ac7ddfbfSEd Maste     case 'G':
188435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qGroupName:"))
189435933ddSDimitry Andric         return eServerPacketType_qGroupName;
190435933ddSDimitry Andric       if (PACKET_MATCHES("qGetWorkingDir"))
191435933ddSDimitry Andric         return eServerPacketType_qGetWorkingDir;
192435933ddSDimitry Andric       if (PACKET_MATCHES("qGetPid"))
193435933ddSDimitry Andric         return eServerPacketType_qGetPid;
194435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qGetProfileData;"))
195435933ddSDimitry Andric         return eServerPacketType_qGetProfileData;
196435933ddSDimitry Andric       if (PACKET_MATCHES("qGDBServerVersion"))
197435933ddSDimitry Andric         return eServerPacketType_qGDBServerVersion;
198ac7ddfbfSEd Maste       break;
199ac7ddfbfSEd Maste 
200ac7ddfbfSEd Maste     case 'H':
201435933ddSDimitry Andric       if (PACKET_MATCHES("qHostInfo"))
202435933ddSDimitry Andric         return eServerPacketType_qHostInfo;
203ac7ddfbfSEd Maste       break;
204ac7ddfbfSEd Maste 
20535617911SEd Maste     case 'K':
206435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qKillSpawnedProcess"))
207435933ddSDimitry Andric         return eServerPacketType_qKillSpawnedProcess;
20835617911SEd Maste       break;
20935617911SEd Maste 
210ac7ddfbfSEd Maste     case 'L':
211435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qLaunchGDBServer"))
212435933ddSDimitry Andric         return eServerPacketType_qLaunchGDBServer;
213435933ddSDimitry Andric       if (PACKET_MATCHES("qLaunchSuccess"))
214435933ddSDimitry Andric         return eServerPacketType_qLaunchSuccess;
215ac7ddfbfSEd Maste       break;
216ac7ddfbfSEd Maste 
21712b93ac6SEd Maste     case 'M':
218435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qMemoryRegionInfo:"))
219435933ddSDimitry Andric         return eServerPacketType_qMemoryRegionInfo;
220435933ddSDimitry Andric       if (PACKET_MATCHES("qMemoryRegionInfo"))
221435933ddSDimitry Andric         return eServerPacketType_qMemoryRegionInfoSupported;
222435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qModuleInfo:"))
223435933ddSDimitry Andric         return eServerPacketType_qModuleInfo;
22412b93ac6SEd Maste       break;
22512b93ac6SEd Maste 
226ac7ddfbfSEd Maste     case 'P':
227435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qProcessInfoPID:"))
228435933ddSDimitry Andric         return eServerPacketType_qProcessInfoPID;
229435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qPlatform_shell:"))
230435933ddSDimitry Andric         return eServerPacketType_qPlatform_shell;
231435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qPlatform_mkdir:"))
232435933ddSDimitry Andric         return eServerPacketType_qPlatform_mkdir;
233435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qPlatform_chmod:"))
234435933ddSDimitry Andric         return eServerPacketType_qPlatform_chmod;
235435933ddSDimitry Andric       if (PACKET_MATCHES("qProcessInfo"))
236435933ddSDimitry Andric         return eServerPacketType_qProcessInfo;
237ac7ddfbfSEd Maste       break;
238ac7ddfbfSEd Maste 
2399f2f44ceSEd Maste     case 'Q':
240435933ddSDimitry Andric       if (PACKET_MATCHES("qQueryGDBServer"))
241435933ddSDimitry Andric         return eServerPacketType_qQueryGDBServer;
2429f2f44ceSEd Maste       break;
2439f2f44ceSEd Maste 
24412b93ac6SEd Maste     case 'R':
245435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qRcmd,"))
246435933ddSDimitry Andric         return eServerPacketType_qRcmd;
247435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qRegisterInfo"))
248435933ddSDimitry Andric         return eServerPacketType_qRegisterInfo;
24912b93ac6SEd Maste       break;
25035617911SEd Maste 
251ac7ddfbfSEd Maste     case 'S':
252435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qSpeedTest:"))
253435933ddSDimitry Andric         return eServerPacketType_qSpeedTest;
254435933ddSDimitry Andric       if (PACKET_MATCHES("qShlibInfoAddr"))
255435933ddSDimitry Andric         return eServerPacketType_qShlibInfoAddr;
256435933ddSDimitry Andric       if (PACKET_MATCHES("qStepPacketSupported"))
257435933ddSDimitry Andric         return eServerPacketType_qStepPacketSupported;
258435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qSupported"))
259435933ddSDimitry Andric         return eServerPacketType_qSupported;
260435933ddSDimitry Andric       if (PACKET_MATCHES("qSyncThreadStateSupported"))
261435933ddSDimitry Andric         return eServerPacketType_qSyncThreadStateSupported;
26212b93ac6SEd Maste       break;
26312b93ac6SEd Maste 
26412b93ac6SEd Maste     case 'T':
265435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qThreadExtraInfo,"))
266435933ddSDimitry Andric         return eServerPacketType_qThreadExtraInfo;
267435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qThreadStopInfo"))
268435933ddSDimitry Andric         return eServerPacketType_qThreadStopInfo;
269ac7ddfbfSEd Maste       break;
270ac7ddfbfSEd Maste 
271ac7ddfbfSEd Maste     case 'U':
272435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qUserName:"))
273435933ddSDimitry Andric         return eServerPacketType_qUserName;
274ac7ddfbfSEd Maste       break;
27512b93ac6SEd Maste 
27612b93ac6SEd Maste     case 'V':
277435933ddSDimitry Andric       if (PACKET_MATCHES("qVAttachOrWaitSupported"))
278435933ddSDimitry Andric         return eServerPacketType_qVAttachOrWaitSupported;
27912b93ac6SEd Maste       break;
28012b93ac6SEd Maste 
28112b93ac6SEd Maste     case 'W':
282435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qWatchpointSupportInfo:"))
283435933ddSDimitry Andric         return eServerPacketType_qWatchpointSupportInfo;
284435933ddSDimitry Andric       if (PACKET_MATCHES("qWatchpointSupportInfo"))
285435933ddSDimitry Andric         return eServerPacketType_qWatchpointSupportInfoSupported;
28612b93ac6SEd Maste       break;
2870127ef0fSEd Maste 
2880127ef0fSEd Maste     case 'X':
289435933ddSDimitry Andric       if (PACKET_STARTS_WITH("qXfer:auxv:read::"))
290435933ddSDimitry Andric         return eServerPacketType_qXfer_auxv_read;
2910127ef0fSEd Maste       break;
292ac7ddfbfSEd Maste     }
293ac7ddfbfSEd Maste     break;
294b91a7dfcSDimitry Andric 
295b91a7dfcSDimitry Andric   case 'j':
296435933ddSDimitry Andric     if (PACKET_STARTS_WITH("jModulesInfo:"))
297435933ddSDimitry Andric       return eServerPacketType_jModulesInfo;
298435933ddSDimitry Andric     if (PACKET_MATCHES("jSignalsInfo"))
299435933ddSDimitry Andric       return eServerPacketType_jSignalsInfo;
300435933ddSDimitry Andric     if (PACKET_MATCHES("jThreadsInfo"))
301435933ddSDimitry Andric       return eServerPacketType_jThreadsInfo;
302302affcbSDimitry Andric     if (PACKET_STARTS_WITH("jTraceBufferRead:"))
303302affcbSDimitry Andric       return eServerPacketType_jTraceBufferRead;
304302affcbSDimitry Andric     if (PACKET_STARTS_WITH("jTraceConfigRead:"))
305302affcbSDimitry Andric       return eServerPacketType_jTraceConfigRead;
306302affcbSDimitry Andric     if (PACKET_STARTS_WITH("jTraceMetaRead:"))
307302affcbSDimitry Andric       return eServerPacketType_jTraceMetaRead;
308302affcbSDimitry Andric     if (PACKET_STARTS_WITH("jTraceStart:"))
309302affcbSDimitry Andric       return eServerPacketType_jTraceStart;
310302affcbSDimitry Andric     if (PACKET_STARTS_WITH("jTraceStop:"))
311302affcbSDimitry Andric       return eServerPacketType_jTraceStop;
3124bb0738eSEd Maste     break;
313b91a7dfcSDimitry Andric 
31435617911SEd Maste   case 'v':
315435933ddSDimitry Andric     if (PACKET_STARTS_WITH("vFile:")) {
316435933ddSDimitry Andric       if (PACKET_STARTS_WITH("vFile:open:"))
317435933ddSDimitry Andric         return eServerPacketType_vFile_open;
318435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:close:"))
319435933ddSDimitry Andric         return eServerPacketType_vFile_close;
320435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:pread"))
321435933ddSDimitry Andric         return eServerPacketType_vFile_pread;
322435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:pwrite"))
323435933ddSDimitry Andric         return eServerPacketType_vFile_pwrite;
324435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:size"))
325435933ddSDimitry Andric         return eServerPacketType_vFile_size;
326435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:exists"))
327435933ddSDimitry Andric         return eServerPacketType_vFile_exists;
328435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:stat"))
329435933ddSDimitry Andric         return eServerPacketType_vFile_stat;
330435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:mode"))
331435933ddSDimitry Andric         return eServerPacketType_vFile_mode;
332435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:MD5"))
333435933ddSDimitry Andric         return eServerPacketType_vFile_md5;
334435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:symlink"))
335435933ddSDimitry Andric         return eServerPacketType_vFile_symlink;
336435933ddSDimitry Andric       else if (PACKET_STARTS_WITH("vFile:unlink"))
337435933ddSDimitry Andric         return eServerPacketType_vFile_unlink;
33835617911SEd Maste 
33912b93ac6SEd Maste     } else {
340435933ddSDimitry Andric       if (PACKET_STARTS_WITH("vAttach;"))
341435933ddSDimitry Andric         return eServerPacketType_vAttach;
342435933ddSDimitry Andric       if (PACKET_STARTS_WITH("vAttachWait;"))
343435933ddSDimitry Andric         return eServerPacketType_vAttachWait;
344435933ddSDimitry Andric       if (PACKET_STARTS_WITH("vAttachOrWait;"))
345435933ddSDimitry Andric         return eServerPacketType_vAttachOrWait;
346435933ddSDimitry Andric       if (PACKET_STARTS_WITH("vAttachName;"))
347435933ddSDimitry Andric         return eServerPacketType_vAttachName;
348435933ddSDimitry Andric       if (PACKET_STARTS_WITH("vCont;"))
349435933ddSDimitry Andric         return eServerPacketType_vCont;
350435933ddSDimitry Andric       if (PACKET_MATCHES("vCont?"))
351435933ddSDimitry Andric         return eServerPacketType_vCont_actions;
35235617911SEd Maste     }
35335617911SEd Maste     break;
35412b93ac6SEd Maste   case '_':
355435933ddSDimitry Andric     switch (packet_cstr[1]) {
35612b93ac6SEd Maste     case 'M':
35712b93ac6SEd Maste       return eServerPacketType__M;
35812b93ac6SEd Maste 
35912b93ac6SEd Maste     case 'm':
36012b93ac6SEd Maste       return eServerPacketType__m;
36112b93ac6SEd Maste     }
36212b93ac6SEd Maste     break;
36312b93ac6SEd Maste 
36412b93ac6SEd Maste   case '?':
365435933ddSDimitry Andric     if (packet_size == 1)
366435933ddSDimitry Andric       return eServerPacketType_stop_reason;
36712b93ac6SEd Maste     break;
36812b93ac6SEd Maste 
36912b93ac6SEd Maste   case 'c':
37012b93ac6SEd Maste     return eServerPacketType_c;
37112b93ac6SEd Maste 
37212b93ac6SEd Maste   case 'C':
37312b93ac6SEd Maste     return eServerPacketType_C;
37412b93ac6SEd Maste 
37512b93ac6SEd Maste   case 'D':
376435933ddSDimitry Andric     if (packet_size == 1)
377435933ddSDimitry Andric       return eServerPacketType_D;
37812b93ac6SEd Maste     break;
37912b93ac6SEd Maste 
38012b93ac6SEd Maste   case 'g':
381435933ddSDimitry Andric     if (packet_size == 1)
382435933ddSDimitry Andric       return eServerPacketType_g;
38312b93ac6SEd Maste     break;
38412b93ac6SEd Maste 
38512b93ac6SEd Maste   case 'G':
38612b93ac6SEd Maste     return eServerPacketType_G;
38712b93ac6SEd Maste 
38812b93ac6SEd Maste   case 'H':
38912b93ac6SEd Maste     return eServerPacketType_H;
39012b93ac6SEd Maste 
3911c3bbb01SEd Maste   case 'I':
3921c3bbb01SEd Maste     return eServerPacketType_I;
3931c3bbb01SEd Maste 
39412b93ac6SEd Maste   case 'k':
395435933ddSDimitry Andric     if (packet_size == 1)
396435933ddSDimitry Andric       return eServerPacketType_k;
39712b93ac6SEd Maste     break;
39812b93ac6SEd Maste 
39912b93ac6SEd Maste   case 'm':
40012b93ac6SEd Maste     return eServerPacketType_m;
40112b93ac6SEd Maste 
40212b93ac6SEd Maste   case 'M':
40312b93ac6SEd Maste     return eServerPacketType_M;
40412b93ac6SEd Maste 
40512b93ac6SEd Maste   case 'p':
40612b93ac6SEd Maste     return eServerPacketType_p;
40712b93ac6SEd Maste 
40812b93ac6SEd Maste   case 'P':
40912b93ac6SEd Maste     return eServerPacketType_P;
41012b93ac6SEd Maste 
41112b93ac6SEd Maste   case 's':
412435933ddSDimitry Andric     if (packet_size == 1)
413435933ddSDimitry Andric       return eServerPacketType_s;
41412b93ac6SEd Maste     break;
41512b93ac6SEd Maste 
41612b93ac6SEd Maste   case 'S':
41712b93ac6SEd Maste     return eServerPacketType_S;
41812b93ac6SEd Maste 
4199f2f44ceSEd Maste   case 'x':
4209f2f44ceSEd Maste     return eServerPacketType_x;
4219f2f44ceSEd Maste 
4229f2f44ceSEd Maste   case 'X':
4239f2f44ceSEd Maste     return eServerPacketType_X;
4249f2f44ceSEd Maste 
42512b93ac6SEd Maste   case 'T':
42612b93ac6SEd Maste     return eServerPacketType_T;
42712b93ac6SEd Maste 
42812b93ac6SEd Maste   case 'z':
42912b93ac6SEd Maste     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
43012b93ac6SEd Maste       return eServerPacketType_z;
43112b93ac6SEd Maste     break;
43212b93ac6SEd Maste 
43312b93ac6SEd Maste   case 'Z':
43412b93ac6SEd Maste     if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
43512b93ac6SEd Maste       return eServerPacketType_Z;
43612b93ac6SEd Maste     break;
437ac7ddfbfSEd Maste   }
438ac7ddfbfSEd Maste   return eServerPacketType_unimplemented;
439ac7ddfbfSEd Maste }
440ac7ddfbfSEd Maste 
IsOKResponse() const441435933ddSDimitry Andric bool StringExtractorGDBRemote::IsOKResponse() const {
442ac7ddfbfSEd Maste   return GetResponseType() == eOK;
443ac7ddfbfSEd Maste }
444ac7ddfbfSEd Maste 
IsUnsupportedResponse() const445435933ddSDimitry Andric bool StringExtractorGDBRemote::IsUnsupportedResponse() const {
446ac7ddfbfSEd Maste   return GetResponseType() == eUnsupported;
447ac7ddfbfSEd Maste }
448ac7ddfbfSEd Maste 
IsNormalResponse() const449435933ddSDimitry Andric bool StringExtractorGDBRemote::IsNormalResponse() const {
450ac7ddfbfSEd Maste   return GetResponseType() == eResponse;
451ac7ddfbfSEd Maste }
452ac7ddfbfSEd Maste 
IsErrorResponse() const453435933ddSDimitry Andric bool StringExtractorGDBRemote::IsErrorResponse() const {
454c4394386SDimitry Andric   return GetResponseType() == eError && isxdigit(m_packet[1]) &&
455c4394386SDimitry Andric          isxdigit(m_packet[2]);
456ac7ddfbfSEd Maste }
457ac7ddfbfSEd Maste 
GetError()458435933ddSDimitry Andric uint8_t StringExtractorGDBRemote::GetError() {
459435933ddSDimitry Andric   if (GetResponseType() == eError) {
460ac7ddfbfSEd Maste     SetFilePos(1);
461ac7ddfbfSEd Maste     return GetHexU8(255);
462ac7ddfbfSEd Maste   }
463ac7ddfbfSEd Maste   return 0;
464ac7ddfbfSEd Maste }
46535617911SEd Maste 
GetStatus()466c4394386SDimitry Andric lldb_private::Status StringExtractorGDBRemote::GetStatus() {
467c4394386SDimitry Andric   lldb_private::Status error;
468c4394386SDimitry Andric   if (GetResponseType() == eError) {
469c4394386SDimitry Andric     SetFilePos(1);
470c4394386SDimitry Andric     uint8_t errc = GetHexU8(255);
471c4394386SDimitry Andric     error.SetError(errc, lldb::eErrorTypeGeneric);
472c4394386SDimitry Andric 
473c4394386SDimitry Andric     error.SetErrorStringWithFormat("Error %u", errc);
474c4394386SDimitry Andric     std::string error_messg;
475c4394386SDimitry Andric     if (GetChar() == ';') {
476c4394386SDimitry Andric       GetHexByteString(error_messg);
477c4394386SDimitry Andric       error.SetErrorString(error_messg);
478c4394386SDimitry Andric     }
479c4394386SDimitry Andric   }
480c4394386SDimitry Andric   return error;
481c4394386SDimitry Andric }
482c4394386SDimitry Andric 
GetEscapedBinaryData(std::string & str)483435933ddSDimitry Andric size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) {
484435933ddSDimitry Andric   // Just get the data bytes in the string as
4854ba319b5SDimitry Andric   // GDBRemoteCommunication::CheckForPacket() already removes any 0x7d escaped
4864ba319b5SDimitry Andric   // characters. If any 0x7d characters are left in the packet, then they are
4874ba319b5SDimitry Andric   // supposed to be there...
48835617911SEd Maste   str.clear();
4897aa51b79SEd Maste   const size_t bytes_left = GetBytesLeft();
490435933ddSDimitry Andric   if (bytes_left > 0) {
4917aa51b79SEd Maste     str.assign(m_packet, m_index, bytes_left);
4927aa51b79SEd Maste     m_index += bytes_left;
49335617911SEd Maste   }
49435617911SEd Maste   return str.size();
49535617911SEd Maste }
49635617911SEd Maste 
4974bb0738eSEd Maste static bool
OKErrorNotSupportedResponseValidator(void *,const StringExtractorGDBRemote & response)498435933ddSDimitry Andric OKErrorNotSupportedResponseValidator(void *,
499435933ddSDimitry Andric                                      const StringExtractorGDBRemote &response) {
500435933ddSDimitry Andric   switch (response.GetResponseType()) {
5014bb0738eSEd Maste   case StringExtractorGDBRemote::eOK:
5024bb0738eSEd Maste   case StringExtractorGDBRemote::eError:
5034bb0738eSEd Maste   case StringExtractorGDBRemote::eUnsupported:
5044bb0738eSEd Maste     return true;
5054bb0738eSEd Maste 
5064bb0738eSEd Maste   case StringExtractorGDBRemote::eAck:
5074bb0738eSEd Maste   case StringExtractorGDBRemote::eNack:
5084bb0738eSEd Maste   case StringExtractorGDBRemote::eResponse:
5094bb0738eSEd Maste     break;
5104bb0738eSEd Maste   }
5114bb0738eSEd Maste   return false;
5124bb0738eSEd Maste }
5134bb0738eSEd Maste 
JSONResponseValidator(void *,const StringExtractorGDBRemote & response)514435933ddSDimitry Andric static bool JSONResponseValidator(void *,
515435933ddSDimitry Andric                                   const StringExtractorGDBRemote &response) {
516435933ddSDimitry Andric   switch (response.GetResponseType()) {
5174bb0738eSEd Maste   case StringExtractorGDBRemote::eUnsupported:
5184bb0738eSEd Maste   case StringExtractorGDBRemote::eError:
5194bb0738eSEd Maste     return true; // Accept unsupported or EXX as valid responses
5204bb0738eSEd Maste 
5214bb0738eSEd Maste   case StringExtractorGDBRemote::eOK:
5224bb0738eSEd Maste   case StringExtractorGDBRemote::eAck:
5234bb0738eSEd Maste   case StringExtractorGDBRemote::eNack:
5244bb0738eSEd Maste     break;
5254bb0738eSEd Maste 
5264bb0738eSEd Maste   case StringExtractorGDBRemote::eResponse:
5274bb0738eSEd Maste     // JSON that is returned in from JSON query packets is currently always
5284ba319b5SDimitry Andric     // either a dictionary which starts with a '{', or an array which starts
5294ba319b5SDimitry Andric     // with a '['. This is a quick validator to just make sure the response
5304ba319b5SDimitry Andric     // could be valid JSON without having to validate all of the
5314bb0738eSEd Maste     // JSON content.
532435933ddSDimitry Andric     switch (response.GetStringRef()[0]) {
533435933ddSDimitry Andric     case '{':
534435933ddSDimitry Andric       return true;
535435933ddSDimitry Andric     case '[':
536435933ddSDimitry Andric       return true;
5374bb0738eSEd Maste     default:
5384bb0738eSEd Maste       break;
5394bb0738eSEd Maste     }
5404bb0738eSEd Maste     break;
5414bb0738eSEd Maste   }
5424bb0738eSEd Maste   return false;
5434bb0738eSEd Maste }
5444bb0738eSEd Maste 
5454bb0738eSEd Maste static bool
ASCIIHexBytesResponseValidator(void *,const StringExtractorGDBRemote & response)546435933ddSDimitry Andric ASCIIHexBytesResponseValidator(void *,
547435933ddSDimitry Andric                                const StringExtractorGDBRemote &response) {
548435933ddSDimitry Andric   switch (response.GetResponseType()) {
5494bb0738eSEd Maste   case StringExtractorGDBRemote::eUnsupported:
5504bb0738eSEd Maste   case StringExtractorGDBRemote::eError:
5514bb0738eSEd Maste     return true; // Accept unsupported or EXX as valid responses
5524bb0738eSEd Maste 
5534bb0738eSEd Maste   case StringExtractorGDBRemote::eOK:
5544bb0738eSEd Maste   case StringExtractorGDBRemote::eAck:
5554bb0738eSEd Maste   case StringExtractorGDBRemote::eNack:
5564bb0738eSEd Maste     break;
5574bb0738eSEd Maste 
558435933ddSDimitry Andric   case StringExtractorGDBRemote::eResponse: {
5594bb0738eSEd Maste     uint32_t valid_count = 0;
560435933ddSDimitry Andric     for (const char ch : response.GetStringRef()) {
561435933ddSDimitry Andric       if (!isxdigit(ch)) {
5624bb0738eSEd Maste         return false;
5634bb0738eSEd Maste       }
5644bb0738eSEd Maste       if (++valid_count >= 16)
565435933ddSDimitry Andric         break; // Don't validate all the characters in case the packet is very
566435933ddSDimitry Andric                // large
5674bb0738eSEd Maste     }
5684bb0738eSEd Maste     return true;
569435933ddSDimitry Andric   } break;
5704bb0738eSEd Maste   }
5714bb0738eSEd Maste   return false;
5724bb0738eSEd Maste }
5734bb0738eSEd Maste 
CopyResponseValidator(const StringExtractorGDBRemote & rhs)574435933ddSDimitry Andric void StringExtractorGDBRemote::CopyResponseValidator(
575435933ddSDimitry Andric     const StringExtractorGDBRemote &rhs) {
5764bb0738eSEd Maste   m_validator = rhs.m_validator;
5774bb0738eSEd Maste   m_validator_baton = rhs.m_validator_baton;
5784bb0738eSEd Maste }
5794bb0738eSEd Maste 
SetResponseValidator(ResponseValidatorCallback callback,void * baton)580435933ddSDimitry Andric void StringExtractorGDBRemote::SetResponseValidator(
581435933ddSDimitry Andric     ResponseValidatorCallback callback, void *baton) {
5824bb0738eSEd Maste   m_validator = callback;
5834bb0738eSEd Maste   m_validator_baton = baton;
5844bb0738eSEd Maste }
5854bb0738eSEd Maste 
SetResponseValidatorToOKErrorNotSupported()586435933ddSDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToOKErrorNotSupported() {
5874bb0738eSEd Maste   m_validator = OKErrorNotSupportedResponseValidator;
5884bb0738eSEd Maste   m_validator_baton = nullptr;
5894bb0738eSEd Maste }
5904bb0738eSEd Maste 
SetResponseValidatorToASCIIHexBytes()591435933ddSDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToASCIIHexBytes() {
5924bb0738eSEd Maste   m_validator = ASCIIHexBytesResponseValidator;
5934bb0738eSEd Maste   m_validator_baton = nullptr;
5944bb0738eSEd Maste }
5954bb0738eSEd Maste 
SetResponseValidatorToJSON()596435933ddSDimitry Andric void StringExtractorGDBRemote::SetResponseValidatorToJSON() {
5974bb0738eSEd Maste   m_validator = JSONResponseValidator;
5984bb0738eSEd Maste   m_validator_baton = nullptr;
5994bb0738eSEd Maste }
6004bb0738eSEd Maste 
ValidateResponse() const601435933ddSDimitry Andric bool StringExtractorGDBRemote::ValidateResponse() const {
6024bb0738eSEd Maste   // If we have a validator callback, try to validate the callback
6034bb0738eSEd Maste   if (m_validator)
6044bb0738eSEd Maste     return m_validator(m_validator_baton, *this);
6054bb0738eSEd Maste   else
6064bb0738eSEd Maste     return true; // No validator, so response is valid
6074bb0738eSEd Maste }
608