xref: /llvm-project/lldb/source/Utility/StringExtractorGDBRemote.cpp (revision 106d02866d4d54b09c08e6a12915dba58e709294)
1 //===-- StringExtractorGDBRemote.cpp ----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // C Includes
11 #include <string.h>
12 
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "Utility/StringExtractorGDBRemote.h"
17 
18 
19 
20 StringExtractorGDBRemote::ResponseType
21 StringExtractorGDBRemote::GetResponseType () const
22 {
23     if (m_packet.empty())
24         return eUnsupported;
25 
26     switch (m_packet[0])
27     {
28     case 'E':
29         if (m_packet.size() == 3 &&
30             isxdigit(m_packet[1]) &&
31             isxdigit(m_packet[2]))
32             return eError;
33         break;
34 
35     case 'O':
36         if (m_packet.size() == 2 && m_packet[1] == 'K')
37             return eOK;
38         break;
39 
40     case '+':
41         if (m_packet.size() == 1)
42             return eAck;
43         break;
44 
45     case '-':
46         if (m_packet.size() == 1)
47             return eNack;
48         break;
49     }
50     return eResponse;
51 }
52 
53 StringExtractorGDBRemote::ServerPacketType
54 StringExtractorGDBRemote::GetServerPacketType () const
55 {
56 #define PACKET_MATCHES(s) ((packet_size == (sizeof(s)-1)) && (strcmp((packet_cstr),(s)) == 0))
57 #define PACKET_STARTS_WITH(s) ((packet_size >= (sizeof(s)-1)) && ::strncmp(packet_cstr, s, (sizeof(s)-1))==0)
58 
59     // Empty is not a supported packet...
60     if (m_packet.empty())
61         return eServerPacketType_invalid;
62 
63     const size_t packet_size = m_packet.size();
64     const char *packet_cstr = m_packet.c_str();
65     switch (m_packet[0])
66     {
67     case '\x03':
68         if (packet_size == 1) return eServerPacketType_interrupt;
69         break;
70 
71     case '-':
72         if (packet_size == 1) return eServerPacketType_nack;
73         break;
74 
75     case '+':
76         if (packet_size == 1) return eServerPacketType_ack;
77         break;
78 
79     case 'A':
80         return eServerPacketType_A;
81 
82     case 'Q':
83 
84         switch (packet_cstr[1])
85         {
86         case 'E':
87             if (PACKET_STARTS_WITH ("QEnvironment:"))           return eServerPacketType_QEnvironment;
88             if (PACKET_STARTS_WITH ("QEnvironmentHexEncoded:")) return eServerPacketType_QEnvironmentHexEncoded;
89             break;
90 
91         case 'S':
92             if (PACKET_MATCHES ("QStartNoAckMode"))               return eServerPacketType_QStartNoAckMode;
93             if (PACKET_STARTS_WITH ("QSaveRegisterState"))        return eServerPacketType_QSaveRegisterState;
94             if (PACKET_STARTS_WITH ("QSetDisableASLR:"))          return eServerPacketType_QSetDisableASLR;
95             if (PACKET_STARTS_WITH ("QSetDetachOnError:"))        return eServerPacketType_QSetDetachOnError;
96             if (PACKET_STARTS_WITH ("QSetSTDIN:"))                return eServerPacketType_QSetSTDIN;
97             if (PACKET_STARTS_WITH ("QSetSTDOUT:"))               return eServerPacketType_QSetSTDOUT;
98             if (PACKET_STARTS_WITH ("QSetSTDERR:"))               return eServerPacketType_QSetSTDERR;
99             if (PACKET_STARTS_WITH ("QSetWorkingDir:"))           return eServerPacketType_QSetWorkingDir;
100             if (PACKET_STARTS_WITH ("QSetLogging:"))              return eServerPacketType_QSetLogging;
101             if (PACKET_STARTS_WITH ("QSetMaxPacketSize:"))        return eServerPacketType_QSetMaxPacketSize;
102             if (PACKET_STARTS_WITH ("QSetMaxPayloadSize:"))       return eServerPacketType_QSetMaxPayloadSize;
103             if (PACKET_STARTS_WITH ("QSetEnableAsyncProfiling;")) return eServerPacketType_QSetEnableAsyncProfiling;
104             if (PACKET_STARTS_WITH ("QSyncThreadState:"))         return eServerPacketType_QSyncThreadState;
105             break;
106 
107         case 'L':
108             if (PACKET_STARTS_WITH ("QLaunchArch:"))              return eServerPacketType_QLaunchArch;
109             if (PACKET_MATCHES("QListThreadsInStopReply"))        return eServerPacketType_QListThreadsInStopReply;
110             break;
111 
112         case 'R':
113             if (PACKET_STARTS_WITH ("QRestoreRegisterState:"))    return eServerPacketType_QRestoreRegisterState;
114             break;
115 
116         case 'T':
117             if (PACKET_MATCHES ("QThreadSuffixSupported"))        return eServerPacketType_QThreadSuffixSupported;
118             break;
119         }
120         break;
121 
122     case 'q':
123         switch (packet_cstr[1])
124         {
125         case 's':
126             if (PACKET_MATCHES ("qsProcessInfo"))               return eServerPacketType_qsProcessInfo;
127             if (PACKET_MATCHES ("qsThreadInfo"))                return eServerPacketType_qsThreadInfo;
128             break;
129 
130         case 'f':
131             if (PACKET_STARTS_WITH ("qfProcessInfo"))           return eServerPacketType_qfProcessInfo;
132             if (PACKET_STARTS_WITH ("qfThreadInfo"))            return eServerPacketType_qfThreadInfo;
133             break;
134 
135         case 'C':
136             if (packet_size == 2)                               return eServerPacketType_qC;
137             break;
138 
139         case 'G':
140             if (PACKET_STARTS_WITH ("qGroupName:"))             return eServerPacketType_qGroupName;
141             if (PACKET_MATCHES ("qGetWorkingDir"))              return eServerPacketType_qGetWorkingDir;
142             if (PACKET_MATCHES ("qGetPid"))                     return eServerPacketType_qGetPid;
143             if (PACKET_STARTS_WITH ("qGetProfileData;"))        return eServerPacketType_qGetProfileData;
144             if (PACKET_MATCHES ("qGDBServerVersion"))           return eServerPacketType_qGDBServerVersion;
145             break;
146 
147         case 'H':
148             if (PACKET_MATCHES ("qHostInfo"))                   return eServerPacketType_qHostInfo;
149             break;
150 
151         case 'K':
152             if (PACKET_STARTS_WITH ("qKillSpawnedProcess"))     return eServerPacketType_qKillSpawnedProcess;
153             break;
154 
155         case 'L':
156             if (PACKET_STARTS_WITH ("qLaunchGDBServer"))        return eServerPacketType_qLaunchGDBServer;
157             if (PACKET_MATCHES ("qLaunchSuccess"))              return eServerPacketType_qLaunchSuccess;
158             break;
159 
160         case 'M':
161             if (PACKET_STARTS_WITH ("qMemoryRegionInfo:"))      return eServerPacketType_qMemoryRegionInfo;
162             if (PACKET_MATCHES ("qMemoryRegionInfo"))           return eServerPacketType_qMemoryRegionInfoSupported;
163             break;
164 
165         case 'P':
166             if (PACKET_STARTS_WITH ("qProcessInfoPID:"))        return eServerPacketType_qProcessInfoPID;
167             if (PACKET_STARTS_WITH ("qPlatform_shell:"))        return eServerPacketType_qPlatform_shell;
168             if (PACKET_STARTS_WITH ("qPlatform_mkdir:"))        return eServerPacketType_qPlatform_mkdir;
169             if (PACKET_STARTS_WITH ("qPlatform_chmod:"))        return eServerPacketType_qPlatform_chmod;
170             if (PACKET_MATCHES ("qProcessInfo"))                return eServerPacketType_qProcessInfo;
171             break;
172 
173         case 'R':
174             if (PACKET_STARTS_WITH ("qRcmd,"))                  return eServerPacketType_qRcmd;
175             if (PACKET_STARTS_WITH ("qRegisterInfo"))           return eServerPacketType_qRegisterInfo;
176             break;
177 
178         case 'S':
179             if (PACKET_STARTS_WITH ("qSpeedTest:"))             return eServerPacketType_qSpeedTest;
180             if (PACKET_MATCHES ("qShlibInfoAddr"))              return eServerPacketType_qShlibInfoAddr;
181             if (PACKET_MATCHES ("qStepPacketSupported"))        return eServerPacketType_qStepPacketSupported;
182             if (PACKET_MATCHES ("qSyncThreadStateSupported"))   return eServerPacketType_qSyncThreadStateSupported;
183             break;
184 
185         case 'T':
186             if (PACKET_STARTS_WITH ("qThreadExtraInfo,"))       return eServerPacketType_qThreadExtraInfo;
187             if (PACKET_STARTS_WITH ("qThreadStopInfo"))         return eServerPacketType_qThreadStopInfo;
188             break;
189 
190         case 'U':
191             if (PACKET_STARTS_WITH ("qUserName:"))              return eServerPacketType_qUserName;
192             break;
193 
194         case 'V':
195             if (PACKET_MATCHES ("qVAttachOrWaitSupported"))     return eServerPacketType_qVAttachOrWaitSupported;
196             break;
197 
198         case 'W':
199             if (PACKET_STARTS_WITH ("qWatchpointSupportInfo:")) return eServerPacketType_qWatchpointSupportInfo;
200             if (PACKET_MATCHES ("qWatchpointSupportInfo"))      return eServerPacketType_qWatchpointSupportInfoSupported;
201             break;
202         }
203         break;
204     case 'v':
205             if (PACKET_STARTS_WITH("vFile:"))
206             {
207                 if (PACKET_STARTS_WITH("vFile:open:"))          return eServerPacketType_vFile_open;
208                 else if (PACKET_STARTS_WITH("vFile:close:"))    return eServerPacketType_vFile_close;
209                 else if (PACKET_STARTS_WITH("vFile:pread"))     return eServerPacketType_vFile_pread;
210                 else if (PACKET_STARTS_WITH("vFile:pwrite"))    return eServerPacketType_vFile_pwrite;
211                 else if (PACKET_STARTS_WITH("vFile:size"))      return eServerPacketType_vFile_size;
212                 else if (PACKET_STARTS_WITH("vFile:exists"))    return eServerPacketType_vFile_exists;
213                 else if (PACKET_STARTS_WITH("vFile:stat"))      return eServerPacketType_vFile_stat;
214                 else if (PACKET_STARTS_WITH("vFile:mode"))      return eServerPacketType_vFile_mode;
215                 else if (PACKET_STARTS_WITH("vFile:MD5"))       return eServerPacketType_vFile_md5;
216                 else if (PACKET_STARTS_WITH("vFile:symlink"))   return eServerPacketType_vFile_symlink;
217                 else if (PACKET_STARTS_WITH("vFile:unlink"))    return eServerPacketType_vFile_unlink;
218 
219             } else {
220               if (PACKET_STARTS_WITH ("vAttach;"))              return eServerPacketType_vAttach;
221               if (PACKET_STARTS_WITH ("vAttachWait;"))          return eServerPacketType_vAttachWait;
222               if (PACKET_STARTS_WITH ("vAttachOrWait;"))        return eServerPacketType_vAttachOrWait;
223               if (PACKET_STARTS_WITH ("vAttachName;"))          return eServerPacketType_vAttachName;
224               if (PACKET_STARTS_WITH("vCont;"))                 return eServerPacketType_vCont;
225               if (PACKET_MATCHES ("vCont?"))                    return eServerPacketType_vCont_actions;
226             }
227             break;
228       case '_':
229         switch (packet_cstr[1])
230         {
231         case 'M':
232             return eServerPacketType__M;
233 
234         case 'm':
235             return eServerPacketType__m;
236         }
237         break;
238 
239       case '?':
240         if (packet_size == 1) return eServerPacketType_stop_reason;
241         break;
242 
243       case 'c':
244         return eServerPacketType_c;
245 
246       case 'C':
247         return eServerPacketType_C;
248 
249       case 'D':
250         if (packet_size == 1) return eServerPacketType_D;
251         break;
252 
253       case 'g':
254         if (packet_size == 1) return eServerPacketType_g;
255         break;
256 
257       case 'G':
258         return eServerPacketType_G;
259 
260       case 'H':
261         return eServerPacketType_H;
262 
263       case 'k':
264         if (packet_size == 1) return eServerPacketType_k;
265         break;
266 
267       case 'm':
268         return eServerPacketType_m;
269 
270       case 'M':
271         return eServerPacketType_M;
272 
273       case 'p':
274         return eServerPacketType_p;
275 
276       case 'P':
277         return eServerPacketType_P;
278 
279       case 's':
280         if (packet_size == 1) return eServerPacketType_s;
281         break;
282 
283       case 'S':
284         return eServerPacketType_S;
285 
286       case 'T':
287         return eServerPacketType_T;
288 
289       case 'z':
290         if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
291           return eServerPacketType_z;
292         break;
293 
294       case 'Z':
295         if (packet_cstr[1] >= '0' && packet_cstr[1] <= '4')
296           return eServerPacketType_Z;
297         break;
298     }
299     return eServerPacketType_unimplemented;
300 }
301 
302 bool
303 StringExtractorGDBRemote::IsOKResponse() const
304 {
305     return GetResponseType () == eOK;
306 }
307 
308 
309 bool
310 StringExtractorGDBRemote::IsUnsupportedResponse() const
311 {
312     return GetResponseType () == eUnsupported;
313 }
314 
315 bool
316 StringExtractorGDBRemote::IsNormalResponse() const
317 {
318     return GetResponseType () == eResponse;
319 }
320 
321 bool
322 StringExtractorGDBRemote::IsErrorResponse() const
323 {
324     return GetResponseType () == eError &&
325            m_packet.size() == 3 &&
326            isxdigit(m_packet[1]) &&
327            isxdigit(m_packet[2]);
328 }
329 
330 uint8_t
331 StringExtractorGDBRemote::GetError ()
332 {
333     if (GetResponseType() == eError)
334     {
335         SetFilePos(1);
336         return GetHexU8(255);
337     }
338     return 0;
339 }
340 
341 size_t
342 StringExtractorGDBRemote::GetEscapedBinaryData (std::string &str)
343 {
344     str.clear();
345     char ch;
346     while (GetBytesLeft())
347     {
348         ch = GetChar();
349         if (ch == 0x7d)
350             ch = (GetChar() ^ 0x20);
351         str.append(1,ch);
352     }
353     return str.size();
354 }
355 
356